import logging
import tempfile
import os
from datetime import datetime
from urllib.parse import unquote

import markdown
import matplotlib.pyplot as plt
import pandas as pd
import pdfkit
from fastapi import APIRouter
from pytz import timezone

from client.openai_client import invoke_openai_only_result, invoke_laozhangapi_only_result
from dao.es_dao.card_dao import find_imei, get_card_list
from dao.es_dao.p_health_log_dao import find_health_exception_raw_data
from dao.es_dao.i_iot_run_dao import get_iot_run_data, get_equipment_list
from dao.mongo_dao.sys_depart import find_depart_by_id
from service.battery import get_valid_work_time_detail_group
from utils.mongo_util import db
from utils.oss_util import upload_file_to_oss_nosdk

ai_report_router = APIRouter(prefix='/iotAi/report', tags=['ai', '报表'])


@ai_report_router.post("/worker")
async def worker_report(data: dict) -> dict:
    # 获取工人的IMEI列表
    worker_imei_list = data.get('imei_list')
    if worker_imei_list is None:
        worker_imei_list = await find_imei(data)
    # 获取数据范围
    start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
    # 获取有效工作时间详情
    work_time = await get_valid_work_time_detail_group(worker_imei_list, start_time, end_time)
    # 获取卡片列表
    base_info_list = await get_card_list({'depart': data['projectId']})
    depart_name = ""
    member_name = ""
    if len(base_info_list) > 0:
        depart_name = base_info_list[0].get('departName')
        member_name = base_info_list[0].get('member')
    # 转换为DataFrame
    df_base = pd.DataFrame(base_info_list)
    df_work = pd.DataFrame(work_time)
    df_base['imei'] = df_base['imei'].str[-6:]
    df_work['imei'] = df_work['imei'].str[-6:]

    base_csv_str = df_to_csv_str(df_base, sep="|", header=True)
    work_csv_str = df_to_csv_str(df_work, sep="|", header=True)
    # df_出勤 = await python分析(df_base, df_work, total_days)
    df_all = pd.merge(df_base, df_work, on="imei", how="left")
    df_null = df_all.loc[df_all['total_steps'].isna(), :]
    no_work = df_null[['jobPost', 'nickName', 'jobDutyName']]
    no_work_csv_str = df_to_csv_str(no_work, sep="|", header=True)
    df_clock_in = await get_attendance_rate(df_base, df_work, total_days)
    df_clock_in_csv_str = df_to_csv_str(df_clock_in, sep="|", header=True)

    invoke_str = ""
    api_str = await invoke_openai_only_result(invoke_str)
    api_str = api_str.replace('```html', '').replace('```', '')
    url = md_to_pdf_and_upload(api_str,
                               f"bangni/report/{member_name}_{depart_name}工作分析报告_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf")
    return {'url': f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{url}'}


@ai_report_router.post("/worker/v2")
async def worker_report_v2(data: dict) -> dict:
    """
    员工工作分析报告V2版本 - 重构版
    
    新架构：
    1. 数据获取 → 统计计算 → 表格生成 → AI分析 → 模板渲染 → PDF生成
    2. 清晰的数据流和职责分离
    3. 统计数据全部用Python完成，AI专注文字性分析
    """
    try:
        print(f"🚀 开始生成员工工作分析报告V2，项目ID: {data.get('memberId')}")
        
        # 1. 获取基础信息
        depart = find_depart_by_id(data.get('memberId'))
        member_name = depart.get('name', '未知机构')
        start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
        base_info_list = await get_card_list({'memberId': data['memberId']})
        
        if not base_info_list:
            print("❌ 未找到员工数据")
            return {'status': 0, 'message': '未找到员工数据', 'url': ''}

        print(f"📅 报告时间范围: {start_time.strftime('%Y-%m-%d')} 至 {end_time.strftime('%Y-%m-%d')} (共{total_days}天)")
        print(f"🏢 机构名称: {member_name}")
        # 2. 获取工作时间数据
        worker_imei_list = data.get('imei_list')
        if worker_imei_list is None:
            worker_imei_list = await find_imei(data)
        
        work_time = await get_valid_work_time_detail_group(worker_imei_list, start_time, end_time)
        
        # 转换为DataFrame
        df_base = pd.DataFrame(base_info_list)
        df_work = pd.DataFrame(work_time)
        
        print(f"👥 员工数量: {len(df_base)} 人")
        print(f"🔍 工作记录: {len(df_work)} 条")
        
        # 3. 完整统计计算（新的核心函数）
        print("🔢 开始完整工作统计计算...")
        complete_stats = calculate_work_complete_stats(
            df_base, df_work, start_time, end_time, total_days, member_name
        )
        print(f"✅ 工作统计计算完成，报告类型: {complete_stats['report_info']['type']}")
        
        # 4. 生成HTML表格内容（复用现有函数）
        print("📋 开始生成工作报告表格...")
        report_tables = generate_report_tables(complete_stats)
        print(f"📊 表格生成完成，共{len(report_tables)}个表格")
        
        # 5. 基于表格生成AI分析内容
        print("🤖 开始生成AI工作分析内容...")
        ai_content = await generate_ai_analysis_from_tables(
            report_tables, complete_stats, member_name, start_time, end_time
        )
        print(f"✅ AI分析内容生成完成，长度: {len(ai_content)} 字符")
        
        # 6. 最终报告渲染
        print("🎨 开始渲染最终工作报告...")
        html_content = render_final_report(
            complete_stats, report_tables, ai_content, member_name, start_time, end_time
        )
        print(f"✅ 工作报告渲染完成，HTML长度: {len(html_content)} 字符")
        
        # 7. PDF生成和文件处理
        print("📄 开始PDF生成...")
        generation_start_time = datetime.now()
        filename = f"bangni/report/{member_name}-员工工作分析报告V2-{complete_stats['report_info']['focus']}-{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf"
        
        print(f"📁 PDF文件名: {filename}")
        
        # PDF生成配置
        config = pdfkit.configuration(wkhtmltopdf=r'E:\\wkhtmltopdf\bin\wkhtmltopdf.exe')
        
        with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_pdf:
            temp_pdf_path = temp_pdf.name
            print(f"📂 临时PDF路径: {temp_pdf_path}")
            
            options = {
                'encoding': 'UTF-8',
                'custom-header': [('Accept-Charset', 'UTF-8')],
                'enable-local-file-access': None,
                'page-size': 'A4',
                'margin-top': '0.75in',
                'margin-right': '0.75in',
                'margin-bottom': '0.75in',
                'margin-left': '0.75in',
                'orientation': 'Portrait',
                'print-media-type': None
            }
            
            print("🔧 正在生成PDF...")
            pdfkit.from_string(html_content, temp_pdf_path, configuration=config, options=options)
            print("✅ PDF生成成功")
            
            # 备份和上传
            print("☁️ 开始备份和上传...")
            upload_success, local_path, file_size, upload_error = backup_and_upload_with_retry(
                temp_pdf_path, filename, max_retries=3
            )
            
            if upload_success:
                print(f"✅ 上传成功，文件大小: {file_size} 字节")
            else:
                print(f"❌ 上传失败: {upload_error}")
            
            # 清理临时文件
            try:
                os.unlink(temp_pdf_path)
                print("🗑️ 临时文件清理完成")
            except Exception as cleanup_error:
                print(f"⚠️ 临时文件清理失败: {cleanup_error}")
        
        generation_end_time = datetime.now()
        generation_duration = (generation_end_time - generation_start_time).total_seconds()
        
        print(f"⏱️ PDF生成耗时: {generation_duration:.2f} 秒")
        
        # 8. 创建报告记录
        oss_url = f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{filename}' if upload_success else None
        
        print("📝 创建工作报告记录...")
        report_record = create_report_record(
            member_id=data.get('projectId'),  # 使用projectId作为member_id
            member_name=member_name,
            report_type=complete_stats['report_info']['type'],
            start_time=start_time,
            end_time=end_time,
            local_path=local_path,
            oss_url=oss_url,
            file_size=file_size,
            data_structure=complete_stats['report_info'],
            request_data=data
        )
        
        report_record['generation_duration_seconds'] = generation_duration
        report_record['upload_status'] = 'success' if upload_success else 'failed'
        report_record['upload_error'] = upload_error if upload_error else None
        
        print(f"🎉 员工工作分析报告V2生成完成！")
        print(f"📋 报告摘要:")
        print(f"   - 员工总数: {complete_stats['basic_info']['total_employees']} 人")
        print(f"   - 工作员工: {complete_stats['basic_info']['working_employees']} 人")
        print(f"   - 出勤率: {complete_stats['attendance_analysis']['overall_rate']:.1%}")
        print(f"   - 部门数量: {complete_stats['department_analysis']['department_count']} 个")
        print(f"   - 文件大小: {file_size} 字节")
        print(f"   - 生成耗时: {generation_duration:.2f} 秒")
        
        if upload_success:
            return {
                'status': 1,
                'message': '员工工作分析报告V2生成成功',
                'url': oss_url,
                'report_summary': {
                    'total_employees': complete_stats['basic_info']['total_employees'],
                    'working_employees': complete_stats['basic_info']['working_employees'],
                    'attendance_rate': complete_stats['attendance_analysis']['overall_rate'],
                    'department_count': complete_stats['department_analysis']['department_count'],
                    'file_size': file_size,
                    'generation_duration': generation_duration
                }
            }
        else:
            return {
                'status': 0,
                'message': f'PDF生成成功但上传失败: {upload_error}',
                'url': '',
                'local_path': local_path
            }
            
    except Exception as e:
        print(f"❌ 员工工作分析报告V2生成失败: {str(e)}")
        import traceback
        traceback.print_exc()
        return {
            'status': 0,
            'message': f'报告生成失败: {str(e)}',
            'url': ''
        }


@ai_report_router.post("/worker/health")
async def worker_health(data: dict) -> dict:
    """
    员工健康异常分析报告V2版本 - 重构版
    
    新架构：
    1. 数据获取 → 统计计算 → 表格生成 → AI分析 → 模板渲染 → PDF生成
    2. 清晰的数据流和职责分离
    3. 统计数据标准化，AI基于表格内容分析
    """
    try:
        print(f"🚀 开始生成员工健康异常报告V2，机构ID: {data.get('memberId')}")
        
        # 1. 获取基础信息
        depart = find_depart_by_id(data.get('memberId'))
        member_name = depart.get('name', '未知机构')
        start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
        
        print(f"📅 报告时间范围: {start_time.strftime('%Y-%m-%d')} 至 {end_time.strftime('%Y-%m-%d')} (共{total_days}天)")
        print(f"🏢 机构名称: {member_name}")
        
        # 2. 获取原始数据
        base_info_list = await get_card_list({'memberId': data['memberId']})
        if not base_info_list:
            print("❌ 未找到员工数据")
            return {'status': 0, 'message': '未找到员工数据', 'url': ''}
            
        df_employee_info = pd.DataFrame(base_info_list)
        print(f"👥 员工数量: {len(df_employee_info)} 人")
        print(f"🔍 员工数据字段: {df_employee_info.columns.tolist()}")
        if not df_employee_info.empty:
            print(f"📋 员工数据样例: {df_employee_info.iloc[0].to_dict()}")
        
        # 查询健康异常原始数据
        health_query_params = {
            'startDate': data.get('startDate'),
            'endDate': data.get('endDate'),
            'level': data.get('level', 2),  # 默认查询中度及以上异常
            'size': 10000
        }
        health_exception_data = await find_health_exception_raw_data(health_query_params, [data['memberId']])
        df_health_exception = pd.DataFrame(health_exception_data)
        
        print(f"🔍 健康异常记录: {len(df_health_exception)} 条")
        if not df_health_exception.empty:
            print(f"📊 健康异常数据字段: {df_health_exception.columns.tolist()}")
            print(f"📋 健康异常数据样例: {df_health_exception.iloc[0].to_dict()}")
        else:
            print("ℹ️ 未发现健康异常数据")
        
        # 3. 完整统计计算（新的核心函数）
        print("🔢 开始完整健康统计计算...")
        complete_stats = calculate_health_complete_stats(
            df_employee_info, df_health_exception, start_time, end_time, total_days, member_name
        )
        print(f"✅ 健康统计计算完成，报告类型: {complete_stats['report_info']['type']}")
        
        # 4. 生成HTML表格内容（新函数）
        print("📋 开始生成健康报告表格...")
        report_tables = generate_health_report_tables(complete_stats)
        print(f"📊 表格生成完成，共{len(report_tables)}个表格")
        
        # 5. 基于表格生成AI分析内容
        print("🤖 开始生成AI健康分析内容...")
        ai_content = await generate_health_ai_analysis_from_tables(
            report_tables, complete_stats, member_name, start_time, end_time
        )
        print(f"✅ AI分析内容生成完成，长度: {len(ai_content)} 字符")
        
        # 6. 最终报告渲染
        print("🎨 开始渲染最终健康报告...")
        html_content = render_health_final_report(
            complete_stats, report_tables, ai_content, member_name, start_time, end_time
        )
        print(f"✅ 健康报告渲染完成，HTML长度: {len(html_content)} 字符")
        
        # 7. PDF生成和文件处理
        print("📄 开始PDF生成...")
        generation_start_time = datetime.now()
        filename = f"bangni/report/{member_name}-员工健康异常分析报告V2-{complete_stats['report_info']['focus']}-{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf"
        
        print(f"📁 PDF文件名: {filename}")
        
        # PDF生成
        config = pdfkit.configuration(wkhtmltopdf=r'E:\\wkhtmltopdf\bin\wkhtmltopdf.exe')
        
        with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_pdf:
            temp_pdf_path = temp_pdf.name
            print(f"📂 临时PDF路径: {temp_pdf_path}")
            
            options = {
                'encoding': 'UTF-8',
                'custom-header': [('Accept-Charset', 'UTF-8')],
                'enable-local-file-access': None,
                'page-size': 'A4',
                'margin-top': '0.75in',
                'margin-right': '0.75in',
                'margin-bottom': '0.75in',
                'margin-left': '0.75in',
                'orientation': 'Portrait',
                'print-media-type': None
            }
            
            print("🔧 正在生成PDF...")
            pdfkit.from_string(html_content, temp_pdf_path, configuration=config, options=options)
            print("✅ PDF生成成功")
            
            # 备份和上传
            print("☁️ 开始备份和上传...")
            upload_success, local_path, file_size, upload_error = backup_and_upload_with_retry(
                temp_pdf_path, filename, max_retries=3
            )
            
            if upload_success:
                print(f"✅ 上传成功，文件大小: {file_size} 字节")
            else:
                print(f"❌ 上传失败: {upload_error}")
            
            # 清理临时文件
            try:
                os.unlink(temp_pdf_path)
                print("🗑️ 临时文件清理完成")
            except Exception as cleanup_error:
                print(f"⚠️ 临时文件清理失败: {cleanup_error}")
        
        generation_end_time = datetime.now()
        generation_duration = (generation_end_time - generation_start_time).total_seconds()
        
        print(f"⏱️ PDF生成耗时: {generation_duration:.2f} 秒")
        
        # 8. 创建报告记录
        oss_url = f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{filename}' if upload_success else None
        
        print("📝 创建健康报告记录...")
        report_record = create_report_record(
            member_id=data.get('memberId'),
            member_name=member_name,
            report_type=complete_stats['report_info']['type'],
            start_time=start_time,
            end_time=end_time,
            local_path=local_path,
            oss_url=oss_url,
            file_size=file_size,
            data_structure=complete_stats['report_info'],
            request_data=data
        )
        
        report_record['generation_duration_seconds'] = generation_duration
        report_record['upload_status'] = 'success' if upload_success else 'failed'
        report_record['upload_error'] = upload_error if upload_error else None
        
        # 9. 保存到MongoDB
        print("💾 保存健康报告记录到MongoDB...")
        save_report_to_mongodb(report_record)
        print("✅ 健康报告记录保存成功")
        
        # 10. 返回结果
        result = {
            'status': 1,
            'message': '成功',
            'url': oss_url or '',
            'report_id': report_record['report_id'],
            'local_path': local_path,
            'file_size_mb': report_record['file_size_mb'],
            'upload_success': upload_success,
            'report_info': {
                'type': complete_stats['report_info']['type'],
                'focus': complete_stats['report_info']['focus'],
                'employees': complete_stats['basic_info']['total_employees'],
                'exception_employees': complete_stats['basic_info']['exception_employees'],
                'exception_rate': complete_stats['basic_info']['exception_rate'],
                'health_score': complete_stats['health_assessment']['overall_health_score'],
                'period_days': report_record['stats_period_days'],
                'generation_time': generation_duration
            }
        }
        
        print(f"🎉 健康报告生成完成！URL: {oss_url}")
        print(f"📋 报告信息: {result['report_info']}")
        
        return result
        
    except Exception as e:
        import traceback
        error_detail = traceback.format_exc()
        print(f"员工健康报告V2版本出错: {str(e)}")
        print(f"错误详情: {error_detail}")
        
        return {
            'status': 0,
            'message': f'生成健康报告失败: {str(e)}',
            'url': '',
            'error': str(e)
        }



@ai_report_router.post("/equipment")
async def equipment_statistics(data: dict) -> dict:
    """
      分析设备数据
    """
    # 1. 获取报告机构名称
    depart = find_depart_by_id(data.get('memberId'))
    member_name = depart.get('name')
    # 2. 获取数据时间范围
    start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
    # 3. 获取设备列表
    equipment_entity = await get_equipment_list(data.get('memberId'))
    df_equipment_entity = pd.DataFrame(equipment_entity)
    imei_list = df_equipment_entity['imei'].tolist()
    equipment_entity_str = df_to_csv_str(df_equipment_entity, sep="|", header=True)
    # 4. 获取设备运行数据
    iot_run_data = await get_iot_run_data(data['memberId'], data.get('startDate'),
                                          data.get('endDate'), imei_list=imei_list)
    df_iot_run_data = pd.DataFrame(iot_run_data)
    df_iot_run_data['date'] = df_iot_run_data['date'].str.split('T').str[0]
    df_iot_run_data_str = df_to_csv_str(df_iot_run_data, sep="|", header=True)
    # 5.通过IMEI连接 df_equipment_entity 和 df_iot_run_data
    df_all = pd.merge(df_equipment_entity, df_iot_run_data, on="imei", how="left")
    df_all = df_all.fillna({
        "date": pd.NaT,
        "runtime_hours": 0
    })
    df_group_by_region = df_all.groupby("region_name").agg(
        工作天数=("date", "count"),
    ).reset_index()
    
    # 修复：为每台设备计算有效出勤天数（考虑设备创建时间）
    df_equipment_valid_days = calculate_equipment_valid_days(
        df_equipment_entity, start_time, end_time, total_days
    )
    
    # 按区域汇总有效出勤天数
    df_group_by_region_all_day = df_equipment_valid_days.groupby("region_name").agg(
        所有天数=("有效出勤天数", "sum")
    ).reset_index()
    
    df_region_days = pd.merge(df_group_by_region_all_day, df_group_by_region, on="region_name", how="left")
    # 计算出每个region的出勤率
    df_region_days['大区出勤率'] = (df_region_days['工作天数'] / df_region_days['所有天数']).__round__(2)
    df_region_days['大区'] = df_region_days['region_name']
    # await generate_and_send_report({'df': df_region_days, 'title':'各大区设备出勤率', 'x_label': '大区', 'y_label': '大区出勤率'})

    invoke_str = await get_invoke_str_per_project(start_time=start_time, end_time=end_time,
                                                  df_iot_run_data_str=df_iot_run_data_str,
                                                  equipment_entity_str=equipment_entity_str,
                                                  member_name=member_name, total_days=total_days,
                                                  equipment_count=len(df_equipment_entity))
    api_str = await invoke_openai_only_result(invoke_str)
    api_str = api_str.replace('```html', '').replace('```', '')
    url = md_to_pdf_and_upload(api_str,
                               f"bangni/report/{member_name}-设备工作分析报告_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf")
    data['url'] = f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{url}'
    print(data.get('url'))
    db.report_log.insert_one(data)
    return {'status': 1, 'message': '成功', 'url': data.get('url')}


@ai_report_router.post("/equipment_v2")
async def equipment_statistics_v2(data: dict) -> dict:
    """
    设备数据分析V2版本 - 重构版
    
    新架构：
    1. 数据获取 → 统计计算 → 表格生成 → AI分析 → 模板渲染 → PDF生成
    2. 清晰的数据流和职责分离
    3. 统计数据标准化，AI基于表格内容分析
    """
    try:
        print(f"🚀 开始生成设备统计报告V2，机构ID: {data.get('departId')}")
        
        # 1. 获取基础信息
        # depart = find_depart_by_id(data.get('departId'))
        # member_name = depart.get('name', '未知机构')
        member_name = data.get('departName')
        start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
        
        print(f"📅 报告时间范围: {start_time.strftime('%Y-%m-%d')} 至 {end_time.strftime('%Y-%m-%d')} (共{total_days}天)")
        print(f"🏢 机构名称: {data.get('departName')}")
        
        # 2. 获取原始数据
        equipment_entity = await get_equipment_list(data.get('query_bool'))
        if not equipment_entity:
            print("❌ 未找到设备数据")
            return {'status': 0, 'message': '未找到设备数据', 'url': ''}
            
        df_equipment_entity = pd.DataFrame(equipment_entity)
        imei_list = df_equipment_entity['imei'].tolist()
        
        print(f"📱 设备数量: {len(df_equipment_entity)} 台")
        print(f"📋 IMEI列表: {len(imei_list)} 个")
        print(f"🔍 设备数据字段: {df_equipment_entity.columns.tolist()}")
        if not df_equipment_entity.empty:
            print(f"📋 设备数据样例: {df_equipment_entity.iloc[0].to_dict()}")
        
        iot_run_data = await get_iot_run_data(None, data.get('startDate'),
                                              data.get('endDate'), imei_list=imei_list)
        df_iot_run_data = pd.DataFrame(iot_run_data)
        
        if not df_iot_run_data.empty:
            df_iot_run_data['date'] = df_iot_run_data['date'].str.split('T').str[0]
            print(f"📊 运行数据记录: {len(df_iot_run_data)} 条")
        else:
            print("⚠️ 运行数据为空")
        
        # 3. 完整统计计算（新的核心函数）
        print("🔢 开始完整统计计算...")
        complete_stats = calculate_complete_report_data(
            df_equipment_entity, df_iot_run_data, start_time, end_time, total_days, member_name
        )
        print(f"✅ 统计计算完成，报告类型: {complete_stats['report_info']['type']}")
        
        # 4. 生成HTML表格内容（新函数）
        print("📋 开始生成HTML表格...")
        report_tables = generate_report_tables(complete_stats)
        print(f"📊 表格生成完成，共{len(report_tables)}个表格")
        
        # 5. 基于表格生成AI分析内容
        print("🤖 开始生成AI分析内容...")
        ai_content = await generate_ai_analysis_from_tables(
            report_tables, complete_stats, member_name, start_time, end_time
        )
        print(f"✅ AI分析内容生成完成，长度: {len(ai_content)} 字符")
        
        # 6. 最终报告渲染
        print("🎨 开始渲染最终报告...")
        html_content = render_final_report(
            complete_stats, report_tables, ai_content, member_name, start_time, end_time
        )
        print(f"✅ 报告渲染完成，HTML长度: {len(html_content)} 字符")
        
        # 7. PDF生成和文件处理
        print("📄 开始PDF生成...")
        generation_start_time = datetime.now()
        filename = f"bangni/report/{member_name}-设备工作分析报告V2-{complete_stats['report_info']['focus']}-{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf"
        
        print(f"📁 PDF文件名: {filename}")
        
        # PDF生成
        config = pdfkit.configuration(wkhtmltopdf=r'E:\\wkhtmltopdf\bin\wkhtmltopdf.exe')
        
        with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_pdf:
            temp_pdf_path = temp_pdf.name
            print(f"📂 临时PDF路径: {temp_pdf_path}")
            
            options = {
                'encoding': 'UTF-8',
                'custom-header': [('Accept-Charset', 'UTF-8')],
                'enable-local-file-access': None,
                'page-size': 'A4',
                'margin-top': '0.75in',
                'margin-right': '0.75in',
                'margin-bottom': '0.75in',
                'margin-left': '0.75in',
                'orientation': 'Portrait',
                'print-media-type': None
            }
            
            print("🔧 正在生成PDF...")
            pdfkit.from_string(html_content, temp_pdf_path, configuration=config, options=options)
            print("✅ PDF生成成功")
            
            # 备份和上传
            print("☁️ 开始备份和上传...")
            upload_success, local_path, file_size, upload_error = backup_and_upload_with_retry(
                temp_pdf_path, filename, max_retries=3
            )
            
            if upload_success:
                print(f"✅ 上传成功，文件大小: {file_size} 字节")
            else:
                print(f"❌ 上传失败: {upload_error}")
            
            # 清理临时文件
            try:
                os.unlink(temp_pdf_path)
                print("🗑️ 临时文件清理完成")
            except Exception as cleanup_error:
                print(f"⚠️ 临时文件清理失败: {cleanup_error}")
        
        generation_end_time = datetime.now()
        generation_duration = (generation_end_time - generation_start_time).total_seconds()
        
        print(f"⏱️ PDF生成耗时: {generation_duration:.2f} 秒")
        
        # 8. 创建报告记录
        oss_url = f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{filename}' if upload_success else None
        
        print("📝 创建报告记录...")
        report_record = create_report_record(
            member_id=data.get('departId'),
            member_name=member_name,
            report_type=complete_stats['report_info']['type'],
            start_time=start_time,
            end_time=end_time,
            local_path=local_path,
            oss_url=oss_url,
            file_size=file_size,
            data_structure=complete_stats['report_info'],
            request_data=data
        )
        
        report_record['generation_duration_seconds'] = generation_duration
        report_record['upload_status'] = 'success' if upload_success else 'failed'
        report_record['upload_error'] = upload_error if upload_error else None
        
        # 9. 保存到MongoDB
        print("💾 保存报告记录到MongoDB...")
        save_report_to_mongodb(report_record)
        print("✅ 报告记录保存成功")
        
        # 10. 返回结果
        result = {
            'status': 1, 
            'message': '成功', 
            'url': oss_url or '',
            'report_id': report_record['report_id'],
            'local_path': local_path,
            'file_size_mb': report_record['file_size_mb'],
            'upload_success': upload_success,
            'report_info': {
                'type': complete_stats['report_info']['type'],
                'focus': complete_stats['report_info']['focus'],
                'devices': complete_stats['basic_info']['total_devices'],
                'regions': complete_stats['basic_info']['total_regions'],
                'projects': complete_stats['basic_info']['total_projects'],
                'period_days': report_record['stats_period_days'],
                'generation_time': generation_duration
            }
        }
        
        print(f"🎉 报告生成完成！URL: {oss_url}")
        print(f"📋 报告信息: {result['report_info']}")
        
        return result
        
    except Exception as e:
        import traceback
        error_detail = traceback.format_exc()
        print(f"设备统计V2版本出错: {str(e)}")
        print(f"错误详情: {error_detail}")
        
        return {
            'status': 0, 
            'message': f'生成报告失败: {str(e)}', 
            'url': '',
            'error': str(e)
        }


@ai_report_router.get("/download_center")
async def get_download_center_reports(
    member_id: int = None,
    report_type: str = None,
    start_date: str = None,
    end_date: str = None,
    page: int = 1,
    page_size: int = 20
):
    """
    下载中心 - 获取报告列表
    
    Args:
        member_id: 机构ID（可选）
        report_type: 报告类型（可选）
        start_date: 开始日期（可选，格式：YYYY-MM-DD）
        end_date: 结束日期（可选，格式：YYYY-MM-DD）
        page: 页码（默认1）
        page_size: 每页数量（默认20）
    
    Returns:
        dict: 报告列表和分页信息
    """
    try:
        from utils.mongo_util import db
        from datetime import datetime
        
        # 构建查询条件
        query = {"is_active": True}
        
        if member_id:
            query["member_id"] = member_id
            
        if report_type:
            query["report_type"] = report_type
            
        if start_date:
            if "created_at" not in query:
                query["created_at"] = {}
            query["created_at"]["$gte"] = datetime.strptime(start_date, '%Y-%m-%d')
            
        if end_date:
            if "created_at" not in query:
                query["created_at"] = {}
            query["created_at"]["$lte"] = datetime.strptime(end_date + " 23:59:59", '%Y-%m-%d %H:%M:%S')
        
        # 计算分页
        skip = (page - 1) * page_size
        
        # 执行查询
        cursor = db.reports.find(query).sort("created_at", -1).skip(skip).limit(page_size)
        reports = list(cursor)
        
        # 统计总数
        total_count = db.reports.count_documents(query)
        total_pages = (total_count + page_size - 1) // page_size
        
        # 格式化返回数据
        formatted_reports = []
        for report in reports:
            formatted_report = {
                "report_id": report.get("report_id"),
                "member_name": report.get("member_name"),
                "report_type": report.get("report_type"),
                "report_focus": report.get("report_focus"),
                "report_start_date": report.get("report_start_date"),
                "report_end_date": report.get("report_end_date"),
                "stats_period_days": report.get("stats_period_days"),
                "created_at": report.get("created_at").strftime('%Y-%m-%d %H:%M:%S') if report.get("created_at") else None,
                "file_size_mb": report.get("file_size_mb"),
                "total_devices": report.get("total_devices"),
                "total_regions": report.get("total_regions"),
                "total_projects": report.get("total_projects"),
                "oss_url": report.get("oss_url"),
                "upload_status": report.get("upload_status"),
                "download_count": report.get("download_count", 0),
                "tags": report.get("tags", []),
                "generation_duration_seconds": report.get("generation_duration_seconds")
            }
            formatted_reports.append(formatted_report)
        
        return {
            'status': 1,
            'message': '查询成功',
            'data': {
                'reports': formatted_reports,
                'pagination': {
                    'current_page': page,
                    'page_size': page_size,
                    'total_count': total_count,
                    'total_pages': total_pages,
                    'has_next': page < total_pages,
                    'has_prev': page > 1
                }
            }
        }
        
    except Exception as e:
        return {
            'status': 0,
            'message': f'查询失败: {str(e)}',
            'data': None
        }


@ai_report_router.post("/download_report/{report_id}")
async def download_report(report_id: str):
    """
    下载报告并记录下载次数
    
    Args:
        report_id: 报告ID
    
    Returns:
        dict: 下载链接信息
    """
    try:
        from utils.mongo_util import db
        from datetime import datetime
        
        # 查找报告
        report = db.reports.find_one({"report_id": report_id, "is_active": True})
        
        if not report:
            return {
                'status': 0,
                'message': '报告不存在或已被删除',
                'data': None
            }
        
        # 更新下载计数
        db.reports.update_one(
            {"report_id": report_id},
            {
                "$inc": {"download_count": 1},
                "$set": {"last_download_time": datetime.now()}
            }
        )
        
        # 记录下载日志
        log_upload_operation("REPORT_DOWNLOAD", report_id, True)
        
        return {
            'status': 1,
            'message': '获取下载链接成功',
            'data': {
                'report_id': report_id,
                'download_url': report.get('oss_url'),
                'local_path': report.get('local_file_path'),
                'file_name': report.get('oss_file_name'),
                'file_size_mb': report.get('file_size_mb'),
                'member_name': report.get('member_name'),
                'report_type': report.get('report_type'),
                'report_focus': report.get('report_focus')
            }
        }
        
    except Exception as e:
        log_upload_operation("REPORT_DOWNLOAD", report_id, False, str(e))
        return {
            'status': 0,
            'message': f'下载失败: {str(e)}',
            'data': None
        }


@ai_report_router.get("/download_center/stats")
async def get_download_center_stats(member_id: int = None):
    """
    下载中心统计信息
    
    Args:
        member_id: 机构ID（可选）
    
    Returns:
        dict: 统计信息
    """
    try:
        from utils.mongo_util import db
        
        # 构建查询条件
        query = {"is_active": True}
        if member_id:
            query["member_id"] = member_id
        
        # 统计各种信息
        total_reports = db.reports.count_documents(query)
        
        # 按报告类型统计
        type_pipeline = [
            {"$match": query},
            {"$group": {"_id": "$report_type", "count": {"$sum": 1}}},
            {"$sort": {"count": -1}}
        ]
        type_stats = list(db.reports.aggregate(type_pipeline))
        
        # 按上传状态统计
        status_pipeline = [
            {"$match": query},
            {"$group": {"_id": "$upload_status", "count": {"$sum": 1}}}
        ]
        status_stats = list(db.reports.aggregate(status_pipeline))
        
        # 总文件大小
        size_pipeline = [
            {"$match": query},
            {"$group": {"_id": None, "total_size_mb": {"$sum": "$file_size_mb"}}}
        ]
        size_result = list(db.reports.aggregate(size_pipeline))
        total_size_mb = size_result[0]['total_size_mb'] if size_result else 0
        
        # 最近7天的报告数量
        from datetime import datetime, timedelta
        week_ago = datetime.now() - timedelta(days=7)
        recent_query = query.copy()
        recent_query["created_at"] = {"$gte": week_ago}
        recent_reports = db.reports.count_documents(recent_query)
        
        return {
            'status': 1,
            'message': '统计成功',
            'data': {
                'total_reports': total_reports,
                'total_size_mb': round(total_size_mb, 2),
                'recent_7_days': recent_reports,
                'type_distribution': type_stats,
                'upload_status_distribution': status_stats
            }
        }
        
    except Exception as e:
        return {
            'status': 0,
            'message': f'统计失败: {str(e)}',
            'data': None
        }


@ai_report_router.post("/equipment_project")
async def equipment_statistics_project(data: dict) -> dict:
    """
      分析设备数据
    """
    start_time, end_time, total_days = await get_data_range_from_utc_date_str(data)
    iot_run_data = await get_iot_run_data({'projectId': data['projectId']}, data.get('startDate'), data.get('endDate'))
    df_iot_run_data = pd.DataFrame(iot_run_data)
    df_iot_run_data['imei'] = df_iot_run_data['imei'].str[-6:]
    df_iot_run_data['date'] = df_iot_run_data['date'].str.split('T').str[0]
    equipment_entity = await get_equipment_list({
        "project.id": data['projectId']
    })
    df_equipment_entity = pd.DataFrame(equipment_entity)
    df_equipment_entity['imei'] = df_equipment_entity['imei'].str[-6:]
    equipment_entity_str = df_to_csv_str(df_equipment_entity, sep="|", header=True)
    df_iot_run_data_str = df_to_csv_str(df_iot_run_data, sep="|", header=True)
    # 通过IMEI连接 df_equipment_entity 和 df_iot_run_data
    # await generate_and_send_report({'df': df_region_days, 'title':'各大区设备出勤率', 'x_label': '大区', 'y_label': '大区出勤率'})
    member_name = ''
    project_name = ''
    if len(equipment_entity) > 0:
        member_name = equipment_entity[0].get('member_name')
        project_name = equipment_entity[0].get('project_name')
    invoke_str = await get_invoke_str_project_equipment(start_time, end_time, total_days,
                                                        df_iot_run_data_str, equipment_entity_str,
                                                        len(equipment_entity),
                                                        member_name, project_name)
    api_str: str = await invoke_openai_only_result(invoke_str)
    api_str = api_str.replace('```html', '').replace('```', '')
    url = md_to_pdf_and_upload(api_str,
                               f"bangni/report/{member_name}-{project_name}设备工作分析报告_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}.pdf")
    data.pop('url', f'https://landiwulian.oss-cn-shenzhen.aliyuncs.com/{url}')
    db.report_log.insert_one(data)
    return {'status': 1, 'message': '成功', 'url': data.get('url')}


async def get_invoke_str(df_iot_run_data_str, end_time, equipment_entity, equipment_entity_str, member_name, start_time,
                         total_days):
    invoke_str = (
        f"这是一些清洁设备的工作数据。请帮我分析一下他们的工作情况。你现在要做的是帮我输出一份用于物业保洁公司的日常清洁设备管理整改数据分析报告，"
        f"请严格的计算，不要瞎说八道，也不需要思考很长的逻辑链，你最需要做到的是精确计算，并且给出严谨的回答，但在输出结果中不需要说明这些也不需要"
        f"说你是根据什么来做的。我只要你输出结果"
        f"这是工作数据表：{df_iot_run_data_str}, "
        f"设备基础数据表：{equipment_entity_str}, "
        f"两个表通过IMEI进行链接，展示分析完的结果。需要展示设备信息的时候用设备名称alias，展示工作时间的同时展示时间乘以work_amount，单位是work_unit，"
        f"我要用做物业公司开会报告分析。"
        f"标题为《广东雅净- {start_time.strftime('%Y年%m月%d日')}"
        f"至 {end_time.strftime('%Y年%m月%d日')} 清洁设备工作分析报告"
        f"展示内容需要进行美化，输出完整的html格式，考虑宽度是A4输出因为我最终要输出到pdf里，表格内容都要居中，表头文字要加粗，整体样式要一致。"
        f"如果是纯文字的部分内容要用合适的html展示方式来输出，标题和内容要分清，可以生成一行一列的表格，来展示标题和内容。"
        f"所有结果你经过严格计算，请调用你的统计计算能力，这个时候你是一名严格的数据统计工作者，不要产生幻觉。输出时再考虑一次数据的准确性。"
        f"不要给我XX之类的语言，排名时如果只有一个项目，请一起说明不要计算数据为0的，避免无效无参考价值的数据"
        f"第一部分是他们的整体项目出勤率"
        f"总设备数{len(equipment_entity)}台，应出勤天数为{total_days}天"
        f"根据有出勤统计表来"
        f"根据出勤统计表，将人数和天数进行相乘得出项目总应出勤天数，和实际出勤天数，实际总出勤天数应为{len(df_iot_run_data_str)}得出项目总出勤率"
        f"按这个逻辑再统计每个项目的总应出勤天数和实际出勤天数，展示并相除得出设备出勤率并展示"
        f"完全缺勤设备是没有在工作数据表里出现过却在总设备里面的，"
        f"设备未出勤的天数即为闲置天数，有出勤的设备中，展示闲置率的前三名"
        f"以下关于时间排名的均不算0小时0分钟的"
        f"第二部分是他们每个大区平均有效工作时间，工作面积，以及排名"
        f"第三部分是他们的每个大区各项目各项目平均有效工作时间，分别展示，还要用文字说明，随时间变化的趋势。"
        f"第四部分是每个大区的项目日均工作时间前三名和最后三名。"
        f"第五部分是 以2个小时为达标时间，每个项目的达标率是多少，以及他们的排名"
        f"第六部分是，管理和整改建议。假如你是一名物业保洁管理专家。根据以上数据对项目进行可落地的管理整改建议，并给出原因。建议要求针对数据。不要笼统。比如对某人某岗位进行整改和处理，"
        f"根据一些数据随时间的变化趋势给出一些可能性分析，并给我下一步公司针对设备管理的建议"
        f"合理性分析，并给出一些建议。"
        f"工作时间的单位是分钟，输出的结果换算成小时和分钟的组合。也不需要告诉我你如何思考，你输出的结果必须是不带任何AI味道的，"
        f"结果不是给我看的，是直接给客户看的所以不要有（注：XXX）什么的内容或者你要怎么怎么做。都和我没有关系"
        f"一定不要有任何中间性的文字输出，你输出的任何文字都是面向客户的，是生产环境"
    )
    return invoke_str


async def get_invoke_str_per_project(start_time: datetime, end_time: datetime, equipment_entity_str, total_days,
                                     df_iot_run_data_str, equipment_count, member_name):
    invoke_str = (
        f"这是一些清洁设备的工作数据。请帮我分析一下他们的工作情况。你现在要做的是帮我输出一份用于物业保洁公司的日常清洁设备管理整改数据分析报告，"
        f"请严格的计算，不要瞎说八道，也不需要思考很长的逻辑链，你最需要做到的是精确计算，并且给出严谨的回答，但在输出结果中不需要说明这些也不需要"
        f"说你是根据什么来做的。我只要你输出结果"
        f"这是工作数据表：{df_iot_run_data_str}, "
        f"设备基础数据表：{equipment_entity_str}, "
        f"两个表通过IMEI进行链接，展示分析完的结果。需要展示设备信息的时候用设备名称alias，展示工作时间的同时展示时间乘以work_amount，单位是work_unit，"
        f"我要用做物业公司开会报告分析。"
        f"标题为《{member_name}- {start_time.strftime('%Y年%m月%d日')}"
        f"至 {end_time.strftime('%Y年%m月%d日')} 清洁设备工作分析报告"
        f"展示内容需要进行美化，输出完整的html格式，考虑宽度是A4输出因为我最终要输出到pdf里，表格内容都要居中，表头文字要加粗，整体样式要一致。"
        f"如果是纯文字的部分内容要用合适的html展示方式来输出，标题和内容要分清，可以生成一行一列的表格，来展示标题和内容。"
        f"所有结果你经过严格计算，请调用你的统计计算能力，这个时候你是一名严格的数据统计工作者，不要产生幻觉。输出时再考虑一次数据的准确性。"
        f"不要给我XX之类的语言，排名时如果只有一个项目，请一起说明不要计算数据为0的，避免无效无参考价值的数据"
        f"一下生成的内容每一项我要求展示排名的地方如果数量不够三就只展示排名，这个你要有逻辑要合理"
        f"第一部分是他们的整体项目出勤率"
        f"总设备数{equipment_count}台，应出勤天数为{total_days}天"
        f"根据有出勤统计表来"
        f"根据出勤统计表，将人数和天数进行相乘得出项目总应出勤天数，和实际出勤天数，实际总出勤天数应为{len(df_iot_run_data_str)}得出项目总出勤率"
        f"按这个逻辑再统计每个项目的总应出勤天数和实际出勤天数，展示并相除得出设备出勤率并展示"
        f"完全缺勤设备是没有在工作数据表里出现过却在总设备里面的，"
        f"设备未出勤的天数即为闲置天数，有出勤的设备中，展示闲置率的前三名"
        f"以下关于时间排名的均不算0小时0分钟的"
        # f"第二部分是他们每个项目平均有效工作时间，工作面积，以及排名"
        f"第二部分是他们的每个大区各项目各项目平均有效工作时间，分别展示，还要用文字说明，随时间变化的趋势。"
        f"第三部分是各项目日均工作时间前三名和最后三名。"
        f"第四部分是 以2个小时为达标时间，每个项目的达标率是多少，以及他们的排名"
        f"第五部分是，管理和整改建议。假如你是一名物业保洁管理专家。根据以上数据对项目进行可落地的管理整改建议，并给出原因。建议要求针对数据。不要笼统。比如对某人某岗位进行整改和处理，针对特别异常的数据要特别说明用红字标出"
        f"根据一些数据随时间的变化趋势给出一些可能性分析，并给我下一步公司针对设备管理的建议"
        f"第六部分，我们的设备使用率分别在行业处于什么水平。分设备类型，"
        f"合理性分析，并给出一些建议。"
        f"工作时间的单位是分钟，输出的结果换算成小时和分钟的组合。也不需要告诉我你如何思考，你输出的结果必须是不带任何AI味道的，"
        f"结果不是给我看的，是直接给客户看的所以不要有（注：XXX）什么的内容或者你要怎么怎么做。都和我没有关系"
        f"一定不要有任何中间性的文字输出，你输出的任何文字都是面向客户的，是生产环境，最后也不需要画蛇添足给我解释这些数据怎么得出的，可以做什么，一个多余的字都不要有，一个多余的字都不要有"
    )
    return invoke_str


async def get_invoke_str_project_equipment(start_time, end_time, total_days, df_iot_run_data_str, equipment_entity_str,
                                           equipment_count,
                                           member_name, project_name):
    invoke_str = (
        f"这是一些清洁设备的工作数据。请帮我分析一下他们的工作情况。你现在要做的是帮我输出一份用于物业保洁公司的日常清洁设备管理整改数据分析报告，"
        f"请严格的计算，不要瞎说八道，也不需要思考很长的逻辑链，你最需要做到的是精确计算，并且给出严谨的回答，但在输出结果中不需要说明这些"
        f"这是工作数据表：{df_iot_run_data_str}, "
        f"设备基础数据表：{equipment_entity_str}, "
        f"两个表通过IMEI进行链接，展示分析完的结果。需要展示设备信息的时候用设备名称alias，展示工作时间的同时展示时间乘以work_amount，单位是work_unit，"
        f"我要用做物业公司开会报告分析。"
        f"标题为《{member_name}-{project_name} {start_time.strftime('%Y年%m月%d日')}"
        f"至 {end_time.strftime('%Y年%m月%d日')} 清洁设备工作分析报告"
        f"展示内容需要进行美化，输出完整的html格式，考虑宽度是A4输出因为我最终要输出到pdf里，表格内容都要居中，表头文字要加粗，整体样式要一致。"
        f"如果是纯文字的部分内容要用合适的html展示方式来输出，标题和内容要分清，可以生成一行一列的表格，来展示标题和内容。"
        f"所有结果你经过严格计算，请调用你的统计计算能力，这个时候你是一名严格的数据统计工作者，不要产生幻觉。输出时再考虑一次数据的准确性。"
        f"不要给我XX之类的语言"
        f"第一部分是他们的项目设备出勤率"
        f"总设备数{equipment_count}台，应出勤天数为{total_days}天"
        f"根据有出勤统计表来"
        f"根据出勤统计表，将人数和天数进行相乘得出项目总应出勤天数，和实际出勤天数，实际总出勤天数应为{len(df_iot_run_data_str)}得出项目总出勤率"
        f"按这个逻辑再统计项目的总应出勤天数和实际出勤天数，展示并相除得出设备出勤率并展示"
        f"完全缺勤设备是没有在工作数据表里出现过却在总设备里面的，"
        f"设备未出勤的天数即为闲置天数，有出勤的设备中，展示闲置率的前三名"
        f"以下关于时间排名的均不算0小时0分钟的"
        f"第二部分是项目平均有效工作时间，工作面积，以及排名"
        f"第三部分是项目平均有效工作时间，随时间变化的趋势。"
        # f"第三部分是每个大区的项目日均工作时间前三名和最后三名。"
        f"第四部分是 以2个小时为达标时间，每台设备的达标率是多少，以及他们的排名"
        f"第五部分是，管理和整改建议。假如你是一名物业保洁管理专家。根据以上数据对项目进行可落地的管理整改建议，并给出原因。建议要求针对数据。不要笼统。比如对某人某岗位进行整改和处理，根据一些数据随时间的变化趋势给出一些可能性分析"
        f"合理性分析，并给出一些建议。"
        f"工作时间的单位是分钟，输出的结果换算成小时和分钟的组合。也不需要告诉我你如何思考，你输出的结果必须是不带任何AI味道的，"
        f"结果不是给我看的，是直接给客户看的所以不要有（注：XXX）什么的内容或者你要怎么怎么做。都和我没有关系")
    return invoke_str


def analyze_data_structure(df_equipment_entity):
    """
    分析数据维度，决定报告类型
    
    Args:
        df_equipment_entity: 设备实体数据DataFrame
    
    Returns:
        dict: 包含报告类型和维度信息的字典
    """
    region_count = df_equipment_entity['region_name'].nunique()
    project_count = df_equipment_entity['project_name'].nunique()
    device_count = len(df_equipment_entity)
    
    # 获取具体的区域和项目名称
    regions = df_equipment_entity['region_name'].unique().tolist()
    projects = df_equipment_entity['project_name'].unique().tolist()
    
    # 判断报告类型
    if region_count == 1 and project_count == 1:
        report_type = "single_project"  # 单项目：设备间对比
        focus = "设备横向对比分析"
    elif region_count == 1 and project_count > 1:
        report_type = "single_region"   # 单大区：项目间对比  
        focus = "项目横向对比分析"
    elif region_count > 1 and project_count == 1:
        report_type = "multi_region_single_project"  # 多大区单项目
        focus = "大区横向对比分析"
    else:
        report_type = "multi_dimension" # 多维度：大区+项目层级分析
        focus = "大区级别-项目级别分层分析"
    
    return {
        "report_type": report_type,
        "focus": focus,
        "region_count": region_count,
        "project_count": project_count,
        "device_count": device_count,
        "regions": regions,
        "projects": projects
    }


def calculate_complete_report_data(df_equipment_entity, df_iot_run_data, start_time, end_time, total_days, member_name):
    """
    核心统计计算函数 - 标准化数据结构输出
    
    Args:
        df_equipment_entity: 设备实体数据
        df_iot_run_data: 设备运行数据
        start_time: 开始时间
        end_time: 结束时间
        total_days: 总天数
        member_name: 机构名称
    
    Returns:
        dict: 标准化的完整统计数据
    """
    # 1. 数据预处理
    print(f"📊 设备实体数据IMEI样例: {df_equipment_entity['imei'].head(3).tolist() if not df_equipment_entity.empty else '无数据'}")
    print(f"📊 运行数据IMEI样例: {df_iot_run_data['imei'].head(3).tolist() if not df_iot_run_data.empty else '无数据'}")
    
    df_all = pd.merge(df_equipment_entity, df_iot_run_data, on="imei", how="left")
    print(f"🔗 数据合并结果: {len(df_all)} 条记录")
    print(f"🔗 有运行数据的设备: {df_all['runtime_hours'].notna().sum()} 台")
    
    df_all = df_all.fillna({
        "date": pd.NaT,
        "runtime_hours": 0
    })
    
    # 2. 分析数据维度
    data_structure = analyze_data_structure(df_equipment_entity)
    
    # 3. 计算有效出勤天数
    df_equipment_valid_days = calculate_equipment_valid_days(
        df_equipment_entity, start_time, end_time, total_days
    )
    
    # 4. 区域出勤统计
    df_group_by_region = df_all.groupby("region_name").agg(
        工作天数=("date", "count"),
    ).reset_index()
    
    df_group_by_region_all_day = df_equipment_valid_days.groupby("region_name").agg(
        所有天数=("有效出勤天数", "sum")
    ).reset_index()
    
    df_region_days = pd.merge(df_group_by_region_all_day, df_group_by_region, on="region_name", how="left")
    df_region_days['大区出勤率'] = (df_region_days['工作天数'] / df_region_days['所有天数']).__round__(4)
    
    # 5. 设备工作统计
    device_work_stats = df_all.groupby('imei').agg({
        'runtime_hours': ['sum', 'mean', 'count'],
        'date': 'nunique'
    }).round(2)
    device_work_stats.columns = ['总工作时间', '平均工作时间', '工作记录数', '工作天数']
    device_work_stats = device_work_stats.reset_index()
    
    # 合并设备基础信息
    print(f"🔍 设备基础信息字段: {df_equipment_valid_days.columns.tolist()}")
    device_summary = df_equipment_valid_days[['imei', 'region_name', 'project_name', 'type', '有效出勤天数']].merge(
        device_work_stats, on='imei', how='left'
    ).fillna(0)
    print(f"📋 设备摘要数据样例: {device_summary.head(1).to_dict('records') if not device_summary.empty else '无数据'}")
    
    # 6. 计算整体出勤率
    total_expected_days = df_equipment_valid_days['有效出勤天数'].sum()
    total_actual_days = df_all.dropna(subset=['date']).shape[0]
    overall_attendance_rate = round(total_actual_days / total_expected_days, 4) if total_expected_days > 0 else 0
    
    # 7. 异常设备识别
    working_devices = set(df_all['imei'].unique())
    all_devices = set(df_equipment_valid_days['imei'].unique())
    idle_devices = all_devices - working_devices
    
    # 低效设备（工作时间低于平均值50%）
    if len(device_summary) > 0:
        avg_work_time = device_summary['总工作时间'].mean()
        low_efficiency_devices = device_summary[
            device_summary['总工作时间'] < avg_work_time * 0.5
        ][['imei', 'type', '总工作时间', 'project_name', 'region_name']].to_dict('records')
        print(f"🔍 识别到低效设备: {len(low_efficiency_devices)} 台")
        if low_efficiency_devices:
            print(f"📋 低效设备样例: {low_efficiency_devices[0]}")
    else:
        low_efficiency_devices = []
    
    # 8. 智能排名计算
    rankings = {}
    
    # 分析区域分布情况
    unique_regions = [r for r in data_structure["regions"] if r and r != '未知区域' and r != '未知']
    effective_region_count = len(unique_regions)
    
    # 分析项目分布情况
    unique_projects = [p for p in data_structure["projects"] if p and p != '未知项目' and p != '未知']
    effective_project_count = len(unique_projects)
    
    # 设备排名（始终显示，因为设备级别排名有意义）
    if len(device_summary) > 0:
        # 获取设备排名，包含完整项目信息
        top_devices = device_summary.nlargest(3, '总工作时间')[['imei', 'type', '总工作时间', 'region_name', 'project_name']].to_dict('records')
        bottom_devices = device_summary.nsmallest(3, '总工作时间')[['imei', 'type', '总工作时间', 'region_name', 'project_name']].to_dict('records')
        rankings["top_devices"] = top_devices
        rankings["bottom_devices"] = bottom_devices
        rankings["show_device_rankings"] = True
    
    # 项目排名（智能判断是否需要显示）
    if 'project_name' in df_all.columns and not df_all['project_name'].isna().all() and effective_project_count > 1:
        # 分析项目的区域分布
        project_stats = df_all.groupby(['project_name', 'region_name']).agg({
            'runtime_hours': ['sum', 'mean'],
            'date': 'nunique',
            'imei': 'nunique'
        }).round(2)
        
        # 计算项目级别统计
        project_summary = df_all.groupby('project_name').agg({
            'runtime_hours': ['sum', 'mean'],
            'date': 'nunique',
            'imei': 'nunique',
            'region_name': 'nunique'
        }).round(2)
        project_summary.columns = ['总工作时间', '平均工作时间', '工作天数', '设备数量', '涉及区域数']
        project_summary = project_summary.reset_index()
        
        # 检查项目是否跨区域分布
        cross_region_projects = project_summary[project_summary['涉及区域数'] > 1]
        same_region_projects = project_summary[project_summary['涉及区域数'] == 1]
        
        # 只有在以下情况才显示项目排名：
        # 1. 有多个项目 AND (项目跨区域 OR 同区域但项目数 > 1)
        if len(project_summary) > 1:
            if len(cross_region_projects) > 0 or (effective_region_count == 1 and len(same_region_projects) > 1):
                top_projects = project_summary.nlargest(3, '总工作时间').to_dict('records')
                bottom_projects = project_summary.nsmallest(3, '总工作时间').to_dict('records')
                rankings["top_projects"] = top_projects
                rankings["bottom_projects"] = bottom_projects
                rankings["show_project_rankings"] = True
                
                # 添加项目分布分析
                rankings["project_distribution_analysis"] = {
                    "cross_region_count": len(cross_region_projects),
                    "same_region_count": len(same_region_projects),
                    "total_projects": len(project_summary),
                    "effective_regions": effective_region_count
                }
    
    # 区域排名（只在有多个有效区域时显示）
    if effective_region_count > 1 and len(df_region_days) > 1:
        region_rankings = df_region_days.copy()
        region_rankings['综合得分'] = region_rankings['大区出勤率'] * 100
        
        # 过滤掉无效区域
        valid_regions = region_rankings[
            (region_rankings['region_name'].notna()) & 
            (region_rankings['region_name'] != '未知区域') & 
            (region_rankings['region_name'] != '未知') &
            (region_rankings['region_name'] != '')
        ]
        
        if len(valid_regions) > 1:
            top_regions = valid_regions.nlargest(3, '综合得分')[['region_name', '工作天数', '大区出勤率', '综合得分']].to_dict('records')
            bottom_regions = valid_regions.nsmallest(3, '综合得分')[['region_name', '工作天数', '大区出勤率', '综合得分']].to_dict('records')
            rankings["top_regions"] = top_regions
            rankings["bottom_regions"] = bottom_regions
            rankings["show_region_rankings"] = True
    
    # 添加显示逻辑标志
    rankings["display_logic"] = {
        "effective_regions": effective_region_count,
        "effective_projects": effective_project_count,
        "should_show_region_breakdown": effective_region_count > 1,
        "should_show_project_rankings": rankings.get("show_project_rankings", False),
        "should_show_region_rankings": rankings.get("show_region_rankings", False),
        "primary_region": unique_regions[0] if len(unique_regions) == 1 else None,
        "report_focus_recommendation": "设备分析" if effective_region_count <= 1 and effective_project_count <= 1 else "跨维度分析"
    }
    
    # 9. 构建标准化数据结构
    complete_stats = {
        # 基础信息
        "basic_info": {
            "member_name": member_name,
            "period_start": start_time.strftime('%Y年%m月%d日'),
            "period_end": end_time.strftime('%Y年%m月%d日'),
            "period_days": total_days,
            "total_devices": len(df_equipment_entity),
            "total_regions": data_structure["region_count"],
            "total_projects": data_structure["project_count"],
            "regions_list": data_structure["regions"],
            "projects_list": data_structure["projects"]
        },
        
        # 报告信息
        "report_info": {
            "type": data_structure["report_type"],
            "focus": data_structure["focus"],
            "generation_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        },
        
        # 出勤分析
        "attendance_analysis": {
            "overall_rate": overall_attendance_rate,
            "total_expected_days": int(total_expected_days),
            "total_actual_days": int(total_actual_days),
            "region_breakdown": df_region_days.to_dict('records') if not df_region_days.empty else [],
            "attendance_rate_by_region": df_region_days[['region_name', '大区出勤率']].to_dict('records') if not df_region_days.empty else []
        },
        
        # 设备统计详情
        "device_details": {
            "all_devices": device_summary.to_dict('records'),
            "device_count_by_type": device_summary.groupby('type').size().to_dict() if not device_summary.empty else {},
            "device_count_by_region": device_summary.groupby('region_name').size().to_dict() if not device_summary.empty else {},
            "average_work_time": device_summary['总工作时间'].mean() if not device_summary.empty else 0
        },
        
        # 排名数据
        "rankings": rankings,
        
        # 异常检测
        "anomaly_detection": {
            "idle_devices": list(idle_devices),
            "idle_count": len(idle_devices),
            "low_efficiency_devices": low_efficiency_devices,
            "critical_issues": [],  # 严重问题
            "warnings": []  # 警告
        },
        
        # 性能分析
        "performance_analysis": {
            "efficiency_distribution": {
                "high_efficiency": len([d for d in device_summary.to_dict('records') if d['总工作时间'] > device_summary['总工作时间'].mean() * 1.2]) if not device_summary.empty else 0,
                "normal_efficiency": len([d for d in device_summary.to_dict('records') if device_summary['总工作时间'].mean() * 0.8 <= d['总工作时间'] <= device_summary['总工作时间'].mean() * 1.2]) if not device_summary.empty else 0,
                "low_efficiency": len(low_efficiency_devices)
            },
            "region_performance": df_region_days.to_dict('records') if not df_region_days.empty else [],
            "utilization_rate": len(working_devices) / len(all_devices) if len(all_devices) > 0 else 0
        }
    }
    
    # 10. 添加问题识别
    if len(idle_devices) > 0:
        complete_stats["anomaly_detection"]["critical_issues"].append(f"发现{len(idle_devices)}台完全闲置设备")
    
    if overall_attendance_rate < 0.7:
        complete_stats["anomaly_detection"]["warnings"].append(f"整体出勤率偏低：{overall_attendance_rate:.1%}")
    
    if len(low_efficiency_devices) > len(all_devices) * 0.3:
        complete_stats["anomaly_detection"]["warnings"].append(f"低效设备占比过高：{len(low_efficiency_devices)}/{len(all_devices)}")
    
    return complete_stats


def calculate_work_complete_stats(df_base, df_work, start_time, end_time, total_days, member_name):
    """
    工作报告数据统计计算函数 - 标准化数据结构输出
    基于现有 calculate_complete_report_data 进行增强优化
    
    Args:
        df_base: 员工基础信息数据
        df_work: 工作时间数据
        start_time: 开始时间
        end_time: 结束时间
        total_days: 总天数
        member_name: 机构名称
    
    Returns:
        dict: 标准化的完整工作统计数据
    """
    print(f"💼 开始工作数据统计计算...")
    print(f"👥 员工信息: {len(df_base)} 人")
    print(f"🔍 工作记录: {len(df_work)} 条")
    
    # 1. 数据预处理和关联
    if df_work.empty:
        print("ℹ️ 无工作数据，生成基础员工信息报告")
        df_merged = df_base.copy()
        df_merged['total_steps'] = 0
        df_merged['runtime_hours'] = 0
        df_merged['工作天数'] = 0
    else:
        # 确保IMEI字段格式一致
        df_base['imei'] = df_base['imei'].astype(str).str[-6:]
        df_work['imei'] = df_work['imei'].astype(str).str[-6:]
        
        # 合并数据
        df_merged = pd.merge(df_base, df_work, on="imei", how="left")
        df_merged = df_merged.fillna({
            "total_steps": 0,
            "runtime_hours": 0,
            "工作天数": 0
        })
    
    print(f"🔗 数据合并结果: {len(df_merged)} 条记录")
    print(f"🔗 有工作数据的员工: {df_merged['total_steps'].gt(0).sum()} 人")
    
    # 2. 基础信息统计
    basic_info = {
        "member_name": member_name,
        "period_start": start_time.strftime('%Y-%m-%d'),
        "period_end": end_time.strftime('%Y-%m-%d'),
        "period_days": total_days,
        "total_employees": len(df_base),
        "working_employees": df_merged['total_steps'].gt(0).sum(),
        "total_regions": df_base['departName'].nunique() if 'departName' in df_base.columns else 1,
        "total_projects": df_base['projectId'].nunique() if 'projectId' in df_base.columns else 1
    }
    
    # 3. 出勤分析
    working_df = df_merged[df_merged['total_steps'] > 0].copy()
    non_working_df = df_merged[df_merged['total_steps'] == 0].copy()
    
    overall_attendance_rate = basic_info["working_employees"] / basic_info["total_employees"] if basic_info["total_employees"] > 0 else 0
    
    attendance_analysis = {
        "overall_rate": overall_attendance_rate,
        "working_count": basic_info["working_employees"],
        "non_working_count": len(non_working_df),
        "non_working_list": non_working_df[['jobPost', 'nickName', 'jobDutyName']].to_dict('records') if len(non_working_df) > 0 else []
    }
    
    # 4. 工作效率分析
    if len(working_df) > 0:
        avg_steps = working_df['total_steps'].mean()
        avg_hours = working_df['runtime_hours'].mean() if 'runtime_hours' in working_df.columns else 0
        
        # 效率分级
        high_efficiency = working_df[working_df['total_steps'] >= avg_steps * 1.2]
        medium_efficiency = working_df[(working_df['total_steps'] >= avg_steps * 0.8) & (working_df['total_steps'] < avg_steps * 1.2)]
        low_efficiency = working_df[working_df['total_steps'] < avg_steps * 0.8]
        
        efficiency_analysis = {
            "average_steps": avg_steps,
            "average_hours": avg_hours,
            "high_efficiency_count": len(high_efficiency),
            "medium_efficiency_count": len(medium_efficiency),
            "low_efficiency_count": len(low_efficiency),
            "high_efficiency_employees": high_efficiency[['nickName', 'jobPost', 'total_steps']].to_dict('records'),
            "low_efficiency_employees": low_efficiency[['nickName', 'jobPost', 'total_steps']].to_dict('records')
        }
    else:
        efficiency_analysis = {
            "average_steps": 0,
            "average_hours": 0,
            "high_efficiency_count": 0,
            "medium_efficiency_count": 0,
            "low_efficiency_count": 0,
            "high_efficiency_employees": [],
            "low_efficiency_employees": []
        }
    
    # 5. 部门分析
    if 'departName' in df_merged.columns:
        department_stats = df_merged.groupby('departName').agg({
            'total_steps': ['count', 'sum', 'mean'],
            'nickName': 'count'
        }).round(2)
        
        department_stats.columns = ['工作人数', '总步数', '平均步数', '部门人数']
        department_stats['出勤率'] = (department_stats['工作人数'] / department_stats['部门人数']).round(4)
        department_stats = department_stats.reset_index()
        
        department_analysis = {
            "department_count": len(department_stats),
            "department_details": department_stats.to_dict('records')
        }
    else:
        department_analysis = {
            "department_count": 1,
            "department_details": [{"departName": "默认部门", "工作人数": basic_info["working_employees"], "出勤率": overall_attendance_rate}]
        }
    
    # 6. 异常检测
    anomaly_detection = {
        "critical_issues": [],
        "warnings": [],
        "suggestions": []
    }
    
    # 异常检测逻辑
    if overall_attendance_rate < 0.5:
        anomaly_detection["critical_issues"].append(f"出勤率严重偏低：{overall_attendance_rate:.1%}")
    elif overall_attendance_rate < 0.7:
        anomaly_detection["warnings"].append(f"出勤率偏低：{overall_attendance_rate:.1%}")
    
    if len(non_working_df) > 0:
        anomaly_detection["warnings"].append(f"发现{len(non_working_df)}名员工无工作记录")
    
    if efficiency_analysis["low_efficiency_count"] > basic_info["total_employees"] * 0.3:
        anomaly_detection["warnings"].append(f"低效员工占比过高：{efficiency_analysis['low_efficiency_count']}/{basic_info['total_employees']}")
    
    # 7. 报告元信息
    report_info = {
        "type": "员工工作分析报告V2",
        "focus": "工作效率与出勤分析",
        "data_quality": "完整" if len(working_df) > 0 else "缺失工作数据",
        "analysis_dimensions": ["出勤统计", "效率分析", "部门对比", "异常检测"]
    }
    
    # 8. 整合完整统计数据
    complete_stats = {
        "report_info": report_info,
        "basic_info": basic_info,
        "attendance_analysis": attendance_analysis,
        "efficiency_analysis": efficiency_analysis,
        "department_analysis": department_analysis,
        "anomaly_detection": anomaly_detection,
        "raw_data": {
            "merged_data": df_merged.to_dict('records'),
            "working_employees": working_df.to_dict('records') if len(working_df) > 0 else [],
            "non_working_employees": non_working_df.to_dict('records') if len(non_working_df) > 0 else []
        }
    }
    
    print(f"✅ 工作统计计算完成，报告类型: {complete_stats['report_info']['type']}")
    print(f"📊 出勤率: {complete_stats['attendance_analysis']['overall_rate']:.1%}")
    print(f"🎯 工作员工: {complete_stats['basic_info']['working_employees']}/{complete_stats['basic_info']['total_employees']}")
    
    return complete_stats


def calculate_health_complete_stats(df_employee_info, df_health_exception, start_time, end_time, total_days, member_name):
    """
    健康异常数据统计计算函数 - 标准化数据结构输出
    
    Args:
        df_employee_info: 员工基础信息数据
        df_health_exception: 健康异常数据
        start_time: 开始时间
        end_time: 结束时间
        total_days: 总天数
        member_name: 机构名称
    
    Returns:
        dict: 标准化的完整健康统计数据
    """
    print(f"🩺 开始健康数据统计计算...")
    print(f"👥 员工信息: {len(df_employee_info)} 人")
    print(f"🔍 健康异常记录: {len(df_health_exception)} 条")
    
    # 1. 数据预处理和关联
    if df_health_exception.empty:
        print("ℹ️ 无健康异常数据，生成正常状态报告")
        df_merged = df_employee_info.copy()
        df_merged['异常次数'] = 0
        df_merged['最高异常等级'] = 0
    else:
        # 运动强度过滤：只统计运动强度在2以下的异常（排除高强度运动期间的正常生理反应）
        if 'intensity' in df_health_exception.columns:
            original_count = len(df_health_exception)
            df_health_exception = df_health_exception[df_health_exception['intensity'] <= 2]
            filtered_count = len(df_health_exception)
            print(f"🏃 运动强度过滤: 原始记录{original_count}条 → 过滤后{filtered_count}条 (排除高强度运动期间异常)")
        else:
            print("⚠️ 健康数据中缺少运动强度字段，跳过强度过滤")
        
        if df_health_exception.empty:
            print("ℹ️ 运动强度过滤后无异常数据")
            df_merged = df_employee_info.copy()
            df_merged['异常次数'] = 0
            df_merged['最高异常等级'] = 0
        else:
            # 通过IMEI关联员工信息和健康异常数据
            df_merged = pd.merge(df_health_exception, df_employee_info, on="imei", how="left")
            print(f"🔗 数据关联结果: {len(df_merged)} 条记录")
    
    # 2. 基础统计
    total_employees = len(df_employee_info)
    total_exceptions = len(df_health_exception)
    
    if not df_health_exception.empty:
        unique_exception_employees = df_merged['imei'].nunique()
        exception_rate = round(unique_exception_employees / total_employees, 4) if total_employees > 0 else 0
    else:
        unique_exception_employees = 0
        exception_rate = 0
    
    print(f"📊 基础统计: 总员工{total_employees}人，异常员工{unique_exception_employees}人，异常率{exception_rate:.1%}")
    
    # 3. 异常等级分析
    if not df_health_exception.empty:
        exception_level_stats = df_merged.groupby(['exception_level', 'dataType']).agg({
            'imei': 'count',
            'nickName': lambda x: x.nunique() if x.notna().any() else 0
        }).reset_index()
        exception_level_stats.columns = ['异常等级', '数据类型', '异常次数', '涉及人数']
        
        # 总体异常等级分布
        level_distribution = df_merged.groupby('exception_level').agg({
            'imei': 'count',
            'nickName': lambda x: x.nunique() if x.notna().any() else 0
        }).reset_index()
        level_distribution.columns = ['异常等级', '总异常次数', '涉及人数']
    else:
        exception_level_stats = pd.DataFrame(columns=['异常等级', '数据类型', '异常次数', '涉及人数'])
        level_distribution = pd.DataFrame(columns=['异常等级', '总异常次数', '涉及人数'])
    
    # 4. 员工异常统计
    if not df_health_exception.empty:
        employee_stats = df_merged.groupby(['imei', 'nickName', 'departName']).agg({
            'exception_level': ['count', 'max', 'mean'],
            'dataType': lambda x: list(x.unique()),
            'createDate': ['min', 'max']  # 首次和最后异常时间
        }).reset_index()
        
        # 重命名列
        employee_stats.columns = ['IMEI', '姓名', '项目名称', '异常总次数', '最高异常等级', '平均异常等级', '异常类型', '首次异常时间', '最后异常时间']
        
        # 计算风险等级
        def calculate_employee_risk_level(row):
            max_level = row['最高异常等级']
            total_count = row['异常总次数']
            
            if max_level >= 3 or total_count >= 10:
                return "高风险"
            elif max_level >= 2 or total_count >= 5:
                return "中风险"
            else:
                return "低风险"
        
        employee_stats['风险等级'] = employee_stats.apply(calculate_employee_risk_level, axis=1)
    else:
        employee_stats = pd.DataFrame(columns=['IMEI', '姓名', '项目名称', '异常总次数', '最高异常等级', '平均异常等级', '异常类型', '首次异常时间', '最后异常时间', '风险等级'])
    
    # 5. 项目异常统计
    if not df_health_exception.empty and 'departName' in df_merged.columns:
        project_stats = df_merged.groupby('departName').agg({
            'imei': 'nunique',
            'exception_level': ['count', 'mean', 'max'],
            'dataType': lambda x: len(x.unique())
        }).reset_index()
        project_stats.columns = ['项目名称', '异常人数', '异常总次数', '平均异常等级', '最高异常等级', '异常类型数']
        
        # 计算项目异常率
        project_employee_counts = df_employee_info.groupby('departName').size().reset_index(name='总人数')
        project_stats = project_stats.merge(project_employee_counts, left_on='项目名称', right_on='departName', how='left')
        project_stats['异常率'] = (project_stats['异常人数'] / project_stats['总人数']).round(4)
    else:
        project_stats = pd.DataFrame(columns=['项目名称', '异常人数', '异常总次数', '平均异常等级', '最高异常等级', '异常类型数', '异常率'])
    
    # 6. 数据类型异常统计
    if not df_health_exception.empty:
        datatype_stats = df_merged.groupby('dataType').agg({
            'imei': 'nunique',
            'exception_level': ['count', 'mean', 'max']
        }).reset_index()
        datatype_stats.columns = ['数据类型', '异常人数', '异常次数', '平均异常等级', '最高异常等级']
        
        # 按异常次数排序
        datatype_stats = datatype_stats.sort_values('异常次数', ascending=False)
    else:
        datatype_stats = pd.DataFrame(columns=['数据类型', '异常人数', '异常次数', '平均异常等级', '最高异常等级'])
    
    # 7. 增强时间趋势分析
    time_analysis = {}
    if not df_health_exception.empty:
        # 转换时间格式
        df_merged['datetime'] = pd.to_datetime(df_merged['createDate'])
        df_merged['日期'] = df_merged['datetime'].dt.date
        df_merged['小时'] = df_merged['datetime'].dt.hour
        df_merged['星期'] = df_merged['datetime'].dt.dayofweek  # 0=周一, 6=周日
        df_merged['星期名'] = df_merged['datetime'].dt.day_name()
        
        # 按日期统计
        daily_stats = df_merged.groupby('日期').agg({
            'imei': 'nunique',
            'exception_level': ['count', 'mean', 'max']
        }).reset_index()
        daily_stats.columns = ['日期', '异常人数', '异常次数', '平均异常等级', '最高异常等级']
        
        # 按小时统计（识别高峰时段）
        hourly_stats = df_merged.groupby('小时').agg({
            'imei': 'count',
            'exception_level': ['count', 'mean']
        }).reset_index()
        hourly_stats.columns = ['小时', '异常人次', '异常次数', '平均异常等级']
        hourly_stats = hourly_stats.sort_values('异常次数', ascending=False)
        
        # 按星期统计
        weekly_stats = df_merged.groupby(['星期', '星期名']).agg({
            'imei': 'count',
            'exception_level': ['count', 'mean']
        }).reset_index()
        weekly_stats.columns = ['星期数', '星期名', '异常人次', '异常次数', '平均异常等级']
        weekly_stats = weekly_stats.sort_values('异常次数', ascending=False)
        
        # 异常高峰时段识别
        peak_hours = hourly_stats.head(3)['小时'].tolist()
        peak_days = weekly_stats.head(2)['星期名'].tolist()
        
        # 异常集中度分析
        total_exceptions_for_concentration = len(df_merged)
        if total_exceptions_for_concentration > 0:
            # 计算时间集中度
            top_3_hours_exceptions = hourly_stats.head(3)['异常次数'].sum()
            hour_concentration = (top_3_hours_exceptions / total_exceptions_for_concentration) * 100
            
            top_2_days_exceptions = weekly_stats.head(2)['异常次数'].sum()  
            day_concentration = (top_2_days_exceptions / total_exceptions_for_concentration) * 100
        else:
            hour_concentration = 0
            day_concentration = 0
        
        # 时间模式分析
        time_patterns = []
        if peak_hours:
            if any(h in peak_hours for h in [9, 10, 11, 14, 15, 16]):
                time_patterns.append("工作时间异常集中")
            if any(h in peak_hours for h in [6, 7, 8]):
                time_patterns.append("早晨时段异常频发")
            if any(h in peak_hours for h in [18, 19, 20, 21]):
                time_patterns.append("晚间时段异常增多")
        
        time_analysis = {
            "daily_trends": daily_stats.to_dict('records'),
            "hourly_distribution": hourly_stats.to_dict('records'),
            "weekly_distribution": weekly_stats.to_dict('records'),
            "peak_analysis": {
                "peak_hours": peak_hours,
                "peak_days": peak_days,
                "hour_concentration_rate": round(hour_concentration, 1),
                "day_concentration_rate": round(day_concentration, 1),
                "time_patterns": time_patterns
            },
            "temporal_insights": {
                "most_problematic_hour": hourly_stats.iloc[0]['小时'] if not hourly_stats.empty else None,
                "most_problematic_day": weekly_stats.iloc[0]['星期名'] if not weekly_stats.empty else None,
                "daily_average_exceptions": daily_stats['异常次数'].mean() if not daily_stats.empty else 0,
                "peak_to_average_ratio": (hourly_stats.iloc[0]['异常次数'] / hourly_stats['异常次数'].mean()) if not hourly_stats.empty and hourly_stats['异常次数'].mean() > 0 else 0
            }
        }
    else:
        daily_stats = pd.DataFrame(columns=['日期', '异常人数', '异常次数', '平均异常等级', '最高异常等级'])
        time_analysis = {"daily_trends": [], "hourly_distribution": [], "weekly_distribution": [], "peak_analysis": {}, "temporal_insights": {}}
    
    # 8. 排名计算
    rankings = {}
    
    # 员工风险排名（前10名）
    if not employee_stats.empty:
        # 高风险员工
        high_risk_employees = employee_stats[employee_stats['风险等级'] == '高风险'].nlargest(10, '异常总次数')
        rankings['high_risk_employees'] = high_risk_employees.to_dict('records')
        
        # 异常次数最多的员工
        top_exception_employees = employee_stats.nlargest(10, '异常总次数')
        rankings['top_exception_employees'] = top_exception_employees.to_dict('records')
    
    # 项目风险排名
    if not project_stats.empty:
        rankings['high_risk_projects'] = project_stats.nlargest(5, '异常率').to_dict('records')
        rankings['most_exception_projects'] = project_stats.nlargest(5, '异常总次数').to_dict('records')
    
    # 9. 构建标准化数据结构
    complete_stats = {
        # 基础信息
        "basic_info": {
            "member_name": member_name,
            "period_start": start_time.strftime('%Y年%m月%d日'),
            "period_end": end_time.strftime('%Y年%m月%d日'),
            "period_days": total_days,
            "total_employees": total_employees,
            "total_exceptions": total_exceptions,
            "exception_employees": unique_exception_employees,
            "exception_rate": exception_rate,
            "normal_employees": total_employees - unique_exception_employees
        },
        
        # 报告信息
        "report_info": {
            "type": "员工健康异常分析",
            "focus": "健康监测",
            "generation_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        },
        
        # 异常等级分析
        "exception_level_analysis": {
            "level_distribution": level_distribution.to_dict('records'),
            "type_level_breakdown": exception_level_stats.to_dict('records'),
            "severity_summary": {
                "轻度异常": level_distribution[level_distribution['异常等级'] == 1]['总异常次数'].sum() if not level_distribution.empty else 0,
                "中度异常": level_distribution[level_distribution['异常等级'] == 2]['总异常次数'].sum() if not level_distribution.empty else 0,
                "重度异常": level_distribution[level_distribution['异常等级'] == 3]['总异常次数'].sum() if not level_distribution.empty else 0
            }
        },
        
        # 员工详细数据
        "employee_details": {
            "all_employees": employee_stats.to_dict('records'),
            "risk_distribution": employee_stats['风险等级'].value_counts().to_dict() if not employee_stats.empty else {},
            "average_exceptions_per_employee": employee_stats['异常总次数'].mean() if not employee_stats.empty else 0
        },
        
        # 项目分析
        "project_analysis": {
            "project_breakdown": project_stats.to_dict('records'),
            "highest_risk_project": project_stats.nlargest(1, '异常率').iloc[0].to_dict() if not project_stats.empty else {},
            "project_count": len(project_stats)
        },
        
        # 数据类型分析
        "datatype_analysis": {
            "type_breakdown": datatype_stats.to_dict('records'),
            "most_problematic_type": datatype_stats.iloc[0].to_dict() if not datatype_stats.empty else {},
            "type_count": len(datatype_stats)
        },
        
        # 排名数据
        "rankings": rankings,
        
        # 增强时间分析
        "time_analysis": time_analysis,
        
        # 异常检测和预警
        "anomaly_detection": {
            "high_risk_employees": len(employee_stats[employee_stats['风险等级'] == '高风险']) if not employee_stats.empty else 0,
            "critical_issues": [],
            "warnings": [],
            "urgent_attention_needed": []
        },
        
        # 健康状况评估
        "health_assessment": {
            "overall_health_score": round((1 - exception_rate) * 100, 1),
            "health_status": "良好" if exception_rate < 0.1 else ("一般" if exception_rate < 0.3 else "需要关注"),
            "trend_analysis": "稳定",  # 简化处理
            "improvement_areas": []
        }
    }
    
    # 10. 添加问题识别和建议
    if unique_exception_employees > 0:
        if exception_rate > 0.3:
            complete_stats["anomaly_detection"]["critical_issues"].append(f"异常员工比例过高({exception_rate:.1%})，需要立即关注")
        if not employee_stats.empty and len(employee_stats[employee_stats['风险等级'] == '高风险']) > 0:
            high_risk_count = len(employee_stats[employee_stats['风险等级'] == '高风险'])
            complete_stats["anomaly_detection"]["warnings"].append(f"发现{high_risk_count}名高风险员工")
        
        # 识别需要紧急关注的员工
        if not employee_stats.empty:
            urgent_employees = employee_stats[
                (employee_stats['最高异常等级'] >= 3) | 
                (employee_stats['异常总次数'] >= 10)
            ]
            if not urgent_employees.empty:
                complete_stats["anomaly_detection"]["urgent_attention_needed"] = urgent_employees[['姓名', '项目名称', '异常总次数', '最高异常等级']].to_dict('records')
    
    print(f"✅ 健康统计计算完成")
    print(f"📊 统计摘要: 总员工{total_employees}人，异常员工{unique_exception_employees}人，异常率{exception_rate:.1%}")
    
    return complete_stats


def calculate_report_summary(df_all, df_region_days, df_equipment_valid_days, data_structure):
    """
    计算报告所需的所有统计摘要
    
    Args:
        df_all: 合并后的设备和运行数据
        df_region_days: 区域出勤统计数据
        df_equipment_valid_days: 设备有效出勤天数数据
        data_structure: 数据结构分析结果
    
    Returns:
        dict: 包含所有统计摘要的字典
    """
    summary = {}
    
    # 1. 基础统计
    summary["basic_stats"] = {
        "total_devices": data_structure["device_count"],
        "total_regions": data_structure["region_count"],
        "total_projects": data_structure["project_count"],
        "region_list": data_structure["regions"],
        "project_list": data_structure["projects"]
    }
    
    # 2. 出勤统计
    total_expected_days = df_equipment_valid_days['有效出勤天数'].sum()
    total_actual_days = df_all.dropna(subset=['date']).shape[0]
    overall_attendance_rate = round(total_actual_days / total_expected_days, 4) if total_expected_days > 0 else 0
    
    summary["attendance_stats"] = {
        "total_expected_days": int(total_expected_days),
        "total_actual_days": int(total_actual_days),
        "overall_attendance_rate": overall_attendance_rate,
        "region_attendance": df_region_days.to_dict('records') if not df_region_days.empty else []
    }
    
    # 3. 设备工作时间统计
    device_work_stats = df_all.groupby('imei').agg({
        'runtime_hours': ['sum', 'mean', 'count'],
        'date': 'nunique'
    }).round(2)
    device_work_stats.columns = ['总工作时间', '平均工作时间', '工作记录数', '工作天数']
    device_work_stats = device_work_stats.reset_index()
    
    # 合并设备基础信息
    device_summary = df_equipment_valid_days[['imei', 'region_name', 'project_name', 'type', '有效出勤天数']].merge(
        device_work_stats, on='imei', how='left'
    ).fillna(0)
    
    summary["device_stats"] = device_summary.to_dict('records')
    
    # 4. 排名数据（为所有报告类型生成完整的排名数据）
    rankings = {}
    
    # 设备排名（所有报告类型都需要）
    if len(device_summary) > 0:
        top_devices = device_summary.nlargest(3, '总工作时间')[['imei', 'type', '总工作时间']].to_dict('records')
        bottom_devices = device_summary.nsmallest(3, '总工作时间')[['imei', 'type', '总工作时间']].to_dict('records')
        rankings["top_devices"] = top_devices
        rankings["bottom_devices"] = bottom_devices
    
    # 项目排名（当有项目数据时）
    if 'project_name' in df_all.columns and not df_all['project_name'].isna().all():
        project_stats = df_all.groupby('project_name').agg({
            'runtime_hours': ['sum', 'mean'],
            'date': 'nunique'
        }).round(2)
        project_stats.columns = ['总工作时间', '平均工作时间', '工作天数']
        project_stats = project_stats.reset_index()
        
        if len(project_stats) > 0:
            top_projects = project_stats.nlargest(3, '总工作时间').to_dict('records')
            bottom_projects = project_stats.nsmallest(3, '总工作时间').to_dict('records')
            rankings["top_projects"] = top_projects
            rankings["bottom_projects"] = bottom_projects
    
    # 区域排名（当有多个区域时）
    if len(df_region_days) > 1:
        region_rankings = df_region_days.copy()
        region_rankings['综合得分'] = region_rankings['大区出勤率'] * 100
        top_regions = region_rankings.nlargest(3, '综合得分')[['region_name', '工作天数', '大区出勤率', '综合得分']].to_dict('records')
        bottom_regions = region_rankings.nsmallest(3, '综合得分')[['region_name', '工作天数', '大区出勤率', '综合得分']].to_dict('records')
        rankings["top_regions"] = top_regions
        rankings["bottom_regions"] = bottom_regions
    
    summary["rankings"] = rankings
    
    # 5. 异常设备识别
    working_devices = set(df_all['imei'].unique())
    all_devices = set(df_equipment_valid_days['imei'].unique())
    idle_devices = all_devices - working_devices
    
    # 低效设备（工作时间低于平均值50%）
    if len(device_summary) > 0:
        avg_work_time = device_summary['总工作时间'].mean()
        low_efficiency_devices = device_summary[
            device_summary['总工作时间'] < avg_work_time * 0.5
        ][['imei', 'type', '总工作时间']].to_dict('records')
    else:
        low_efficiency_devices = []
    
    summary["anomaly_devices"] = {
        "idle_devices": list(idle_devices),
        "idle_count": len(idle_devices),
        "low_efficiency_devices": low_efficiency_devices
    }
    
    return summary


def calculate_equipment_valid_days(df_equipment_entity, start_time, end_time, total_days):
    """
    计算每台设备的有效出勤天数，考虑设备创建时间
    
    Args:
        df_equipment_entity: 设备实体数据DataFrame
        start_time: 统计开始时间（datetime对象）
        end_time: 统计结束时间（datetime对象）
        total_days: 总统计天数
    
    Returns:
        DataFrame: 包含每台设备有效出勤天数的数据
    """
    import pandas as pd
    from datetime import datetime
    
    # 复制设备数据
    df_valid_days = df_equipment_entity.copy()
    
    # 将createDate字符串转换为datetime对象进行比较
    def parse_create_date(create_date_str):
        """解析创建日期字符串，支持多种格式"""
        if pd.isna(create_date_str) or create_date_str is None:
            return None
        
        try:
            # 尝试解析ISO格式（如：2024-01-15T10:30:00.000Z）
            if 'T' in str(create_date_str):
                return pd.to_datetime(create_date_str).replace(tzinfo=None)
            else:
                # 尝试解析其他常见格式
                return pd.to_datetime(create_date_str)
        except:
            # 如果解析失败，返回None（视为早于统计开始时间）
            return None
    
    # 解析创建时间
    df_valid_days['创建时间'] = df_valid_days['createDate'].apply(parse_create_date)
    
    # 计算每台设备的有效出勤天数
    def calculate_valid_days(create_date):
        """计算单台设备的有效出勤天数"""
        if create_date is None:
            # 创建时间无效或早于统计开始时间，按全周期计算
            return total_days
        
        # 移除时区信息进行比较
        start_time_naive = start_time.replace(tzinfo=None) if start_time.tzinfo else start_time
        end_time_naive = end_time.replace(tzinfo=None) if end_time.tzinfo else end_time
        
        if create_date <= start_time_naive:
            # 设备创建时间早于或等于统计开始时间，按全周期计算
            return total_days
        elif create_date >= end_time_naive:
            # 设备创建时间晚于统计结束时间，有效天数为0
            return 0
        else:
            # 设备创建时间在统计周期内，从创建时间算到结束时间
            return (end_time_naive - create_date).days + 1
    
    df_valid_days['有效出勤天数'] = df_valid_days['创建时间'].apply(calculate_valid_days)
    
    return df_valid_days


def generate_smart_prompt(summary, data_structure, member_name, start_time, end_time):
    """
    根据数据维度生成对应的AI提示
    
    Args:
        summary: 统计摘要数据
        data_structure: 数据结构分析结果
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: 智能化的AI提示字符串
    """
    import json
    
    # 基础信息
    time_range = f"{start_time.strftime('%Y年%m月%d日')}至{end_time.strftime('%Y年%m月%d日')}"
    report_title = f"《{member_name} {time_range} 清洁设备工作分析报告》"
    
    # 根据报告类型选择对应的提示模板
    if data_structure["report_type"] == "single_project":
        return generate_single_project_prompt(summary, report_title, data_structure)
    elif data_structure["report_type"] == "single_region":
        return generate_single_region_prompt(summary, report_title, data_structure)
    elif data_structure["report_type"] == "multi_region_single_project":
        return generate_multi_region_prompt(summary, report_title, data_structure)
    else:
        return generate_multi_dimension_prompt(summary, report_title, data_structure)


def generate_single_project_prompt(summary, report_title, data_structure):
    """单项目报告提示：重点关注设备间对比"""
    import json
    
    prompt = f"""
你是一名专业的保洁设备数据分析师，现在需要生成一份设备工作分析报告。

**数据已经预计算完成，请严格按照提供的数据生成报告，不要自行计算。**

## 报告标题
{report_title}

## 数据摘要（已计算）
{json.dumps(summary, ensure_ascii=False, indent=2)}

## 报告要求
这是单项目分析，重点关注**设备间横向对比**。

### 报告结构：
1. **项目概况**
   - 项目名称：{data_structure['projects'][0]}
   - 设备总数：{summary['basic_stats']['total_devices']}台
   - 分析周期及基础统计数据

2. **设备出勤率分析**
   - 整体出勤率：{summary['attendance_stats']['overall_attendance_rate']:.2%}
   - 应出勤天数：{summary['attendance_stats']['total_expected_days']}天
   - 实际出勤天数：{summary['attendance_stats']['total_actual_days']}天
   - 完全缺勤设备：{summary['anomaly_devices']['idle_count']}台

3. **设备工作时间对比**
   - 工作时间排名前3名和后3名设备
   - 低效设备识别和分析

4. **问题设备分析**
   - 针对异常设备的具体分析
   - 设备使用效率评估

5. **管理建议**
   - 针对性设备管理建议
   - 提升设备利用率的具体措施

### 输出要求：
- 输出完整HTML格式，适合A4页面
- 表格内容居中，表头加粗
- 数据精确，基于提供的统计结果
- 语言专业，适合管理层会议
- 无AI痕迹，直接面向客户
- 重点突出设备间差异和改进建议
"""
    return prompt


def generate_single_region_prompt(summary, report_title, data_structure):
    """单大区报告提示：重点关注项目间对比"""
    import json
    
    prompt = f"""
你是一名专业的保洁设备数据分析师，现在需要生成一份设备工作分析报告。

**数据已经预计算完成，请严格按照提供的数据生成报告，不要自行计算。**

## 报告标题
{report_title}

## 数据摘要（已计算）
{json.dumps(summary, ensure_ascii=False, indent=2)}

## 报告要求
这是单大区多项目分析，重点关注**项目间横向对比**。

### 报告结构：
1. **大区概况**
   - 大区名称：{data_structure['regions'][0]}
   - 项目数量：{data_structure['project_count']}个
   - 设备总数：{summary['basic_stats']['total_devices']}台

2. **各项目出勤率对比**
   - 整体出勤率：{summary['attendance_stats']['overall_attendance_rate']:.2%}
   - 各项目出勤率排名和对比分析

3. **项目工作效率对比**
   - 项目工作时间排名
   - 项目间效率差异分析

4. **问题项目识别**
   - 低效项目分析
   - 设备闲置项目识别

5. **项目管理建议**
   - 针对各项目的具体改进建议
   - 大区统一管理优化措施

### 输出要求：
- 输出完整HTML格式，适合A4页面
- 表格内容居中，表头加粗
- 数据精确，基于提供的统计结果
- 语言专业，适合管理层会议
- 无AI痕迹，直接面向客户
- 重点突出项目间对比和管理建议
"""
    return prompt


def generate_multi_dimension_prompt(summary, report_title, data_structure):
    """多维度报告提示：大区+项目层级分析"""
    import json
    
    prompt = f"""
你是一名专业的保洁设备数据分析师，现在需要生成一份设备工作分析报告。

**数据已经预计算完成，请严格按照提供的数据生成报告，不要自行计算。**

## 报告标题
{report_title}

## 数据摘要（已计算）
{json.dumps(summary, ensure_ascii=False, indent=2)}

## 报告要求
这是多维度分析，重点进行**大区级别+项目级别分层分析**。

### 报告结构：
1. **整体概况**
   - 覆盖大区：{data_structure['region_count']}个
   - 涉及项目：{data_structure['project_count']}个
   - 设备总数：{summary['basic_stats']['total_devices']}台

2. **大区级别分析**
   - 各大区出勤率对比
   - 大区工作效率排名

3. **项目级别分析**
   - 各项目详细表现
   - 跨大区项目对比

4. **分层问题分析**
   - 大区层面问题识别
   - 项目层面问题分析
   - 设备层面异常统计

5. **分级管理建议**
   - 大区级别管理建议
   - 项目级别改进措施
   - 设备优化配置建议

### 输出要求：
- 输出完整HTML格式，适合A4页面
- 表格内容居中，表头加粗
- 数据精确，基于提供的统计结果
- 语言专业，适合高层管理会议
- 无AI痕迹，直接面向客户
- 重点突出层级化管理和战略建议
"""
    return prompt


def generate_multi_region_prompt(summary, report_title, data_structure):
    """多大区单项目报告提示：重点关注大区间对比"""
    import json
    
    prompt = f"""
你是一名专业的保洁设备数据分析师，现在需要生成一份设备工作分析报告。

**数据已经预计算完成，请严格按照提供的数据生成报告，不要自行计算。**

## 报告标题
{report_title}

## 数据摘要（已计算）
{json.dumps(summary, ensure_ascii=False, indent=2)}

## 报告要求
这是多大区单项目分析，重点关注**大区间横向对比**。

### 报告结构：
1. **项目概况**
   - 项目名称：{data_structure['projects'][0]}
   - 覆盖大区：{data_structure['region_count']}个
   - 设备总数：{summary['basic_stats']['total_devices']}台

2. **各大区出勤率对比**
   - 整体出勤率：{summary['attendance_stats']['overall_attendance_rate']:.2%}
   - 各大区出勤率排名和分析

3. **大区工作效率对比**
   - 大区设备利用率排名
   - 大区间效率差异分析

4. **问题大区识别**
   - 低效大区分析
   - 设备配置不合理大区

5. **大区管理建议**
   - 针对各大区的管理建议
   - 大区间经验推广建议

### 输出要求：
- 输出完整HTML格式，适合A4页面
- 表格内容居中，表头加粗
- 数据精确，基于提供的统计结果
- 语言专业，适合区域管理会议
- 无AI痕迹，直接面向客户
- 重点突出大区间对比和区域优化
"""
    return prompt


async def get_data_range_from_utc_date_str(data):
    # 从data字典中获取开始日期和结束日期
    start_date = data['startDate']
    end_date = data['endDate']
    # 计算总天数
    total_days = (datetime.strptime(end_date, '%Y-%m-%dT%H:%M:%S.%fZ')
                  - datetime.strptime(start_date, '%Y-%m-%dT%H:%M:%S.%fZ')).days + 1
    # 设置时区为北京时间
    beijing_tz = timezone('Asia/Shanghai')
    # 将开始日期和结束日期转换为datetime对象
    start_time = datetime.strptime(start_date, '%Y-%m-%dT%H:%M:%S.%fZ')
    end_time = datetime.strptime(end_date, '%Y-%m-%dT%H:%M:%S.%fZ')
    # 将开始日期和结束日期转换为北京时间
    start_time = start_time.astimezone(beijing_tz)
    end_time = end_time.astimezone(beijing_tz)
    # 返回开始日期、结束日期和总天数
    return start_time, end_time, total_days


def create_report_record(member_id, member_name, report_type, start_time, end_time, 
                        local_path, oss_url, file_size, data_structure, request_data):
    """
    创建完善的报告记录，用于MongoDB存储和下载中心展示
    
    Args:
        member_id: 机构ID
        member_name: 机构名称
        report_type: 报告类型
        start_time: 报告开始时间
        end_time: 报告结束时间
        local_path: 本地文件路径
        oss_url: OSS下载链接
        file_size: 文件大小（字节）
        data_structure: 数据结构分析结果
        request_data: 原始请求数据
    
    Returns:
        dict: 完整的报告记录
    """
    from datetime import datetime
    import os
    
    now = datetime.now()
    
    # 计算统计周期天数
    stats_days = (end_time - start_time).days + 1
    
    # 生成报告ID
    report_id = f"{member_id}_{report_type}_{now.strftime('%Y%m%d%H%M%S%f')[:-3]}"
    
    # 构建完整记录
    record = {
        # 基础信息
        "report_id": report_id,
        "member_id": member_id,
        "member_name": member_name,
        "report_type": report_type,
        "report_version": "v2",
        
        # 时间信息
        "report_start_date": start_time.strftime('%Y-%m-%d'),
        "report_end_date": end_time.strftime('%Y-%m-%d'),
        "report_start_datetime": start_time,
        "report_end_datetime": end_time,
        "stats_period_days": stats_days,
        "created_at": now,
        "upload_time": now,
        
        # 文件信息
        "local_file_path": local_path,
        "oss_url": oss_url,
        "oss_file_name": oss_url.split('/')[-1] if oss_url else None,
        "file_size_bytes": file_size,
        "file_size_mb": round(file_size / (1024 * 1024), 2) if file_size else 0,
        
        # 报告内容信息
        "report_focus": data_structure.get('focus', ''),
        "total_devices": data_structure.get('device_count', 0),
        "total_regions": data_structure.get('region_count', 0),
        "total_projects": data_structure.get('project_count', 0),
        "regions_list": data_structure.get('regions', []),
        "projects_list": data_structure.get('projects', []),
        
        # 生成信息
        "generation_status": "success",
        "upload_status": "success" if oss_url else "failed",
        "generation_duration_seconds": None,  # 可后续计算
        
        # 下载中心相关
        "download_count": 0,
        "last_download_time": None,
        "is_active": True,
        "tags": [
            report_type,
            f"{stats_days}天",
            f"{data_structure.get('device_count', 0)}台设备",
            data_structure.get('focus', '')
        ],
        
        # 原始请求数据
        "request_params": {
            "member_id": request_data.get('memberId'),
            "start_date": request_data.get('startDate'),
            "end_date": request_data.get('endDate'),
            "original_request": request_data
        },
        
        # 扩展信息
        "metadata": {
            "report_format": "pdf",
            "language": "zh-CN",
            "timezone": "Asia/Shanghai",
            "system_version": "v2.0",
            "ai_model": "deepseek"  # 或其他AI模型
        }
    }
    
    return record


def save_report_to_mongodb(report_record):
    """
    保存报告记录到MongoDB
    
    Args:
        report_record: 报告记录字典
    
    Returns:
        bool: 保存是否成功
    """
    try:
        from utils.mongo_util import db
        
        # 保存到reports集合
        result = db.reports.insert_one(report_record)
        
        if result.inserted_id:
            print(f"报告记录已保存到MongoDB: {report_record['report_id']}")
            log_upload_operation("MONGODB_SAVE", report_record['report_id'], True)
            return True
        else:
            error_msg = "MongoDB插入失败"
            print(f"MongoDB保存失败: {error_msg}")
            log_upload_operation("MONGODB_SAVE", report_record['report_id'], False, error_msg)
            return False
            
    except Exception as e:
        error_msg = f"MongoDB保存异常: {str(e)}"
        print(error_msg)
        log_upload_operation("MONGODB_SAVE", report_record.get('report_id', 'unknown'), False, error_msg)
        return False


def get_file_size(file_path):
    """
    获取文件大小
    
    Args:
        file_path: 文件路径
    
    Returns:
        int: 文件大小（字节），失败返回0
    """
    try:
        import os
        if os.path.exists(file_path):
            return os.path.getsize(file_path)
        else:
            return 0
    except Exception as e:
        print(f"获取文件大小失败: {str(e)}")
        return 0


def ensure_local_directory():
    """
    确保本地report目录存在，按日期创建目录结构
    
    Returns:
        str: 当天的本地保存目录路径
    """
    import os
    from datetime import datetime
    
    # 基础目录
    base_dir = "/report"
    
    # 当前日期
    now = datetime.now()
    year = now.strftime("%Y")
    month = now.strftime("%m")
    day = now.strftime("%d")
    
    # 完整目录路径
    today_dir = os.path.join(base_dir, year, month, day)
    logs_dir = os.path.join(base_dir, "upload_logs")
    
    # 创建目录
    try:
        os.makedirs(today_dir, exist_ok=True)
        os.makedirs(logs_dir, exist_ok=True)
        print(f"本地目录已创建: {today_dir}")
        return today_dir
    except Exception as e:
        print(f"创建本地目录失败: {str(e)}")
        # 如果创建失败，使用临时目录
        return os.path.join(base_dir, "temp")


def log_upload_operation(operation, file_path, success, error_msg=None):
    """
    记录上传操作日志
    
    Args:
        operation: 操作类型
        file_path: 文件路径
        success: 是否成功
        error_msg: 错误信息
    """
    import os
    from datetime import datetime
    
    # 日志文件路径
    log_dir = "/report/upload_logs"
    os.makedirs(log_dir, exist_ok=True)
    
    log_file = os.path.join(log_dir, f"{datetime.now().strftime('%Y-%m-%d')}.log")
    
    # 日志内容
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    status = "SUCCESS" if success else "FAILED"
    log_entry = f"[{timestamp}] {operation} - {status} - {file_path}"
    
    if error_msg:
        log_entry += f" - ERROR: {error_msg}"
    
    log_entry += "\n"
    
    # 写入日志
    try:
        with open(log_file, 'a', encoding='utf-8') as f:
            f.write(log_entry)
    except Exception as e:
        print(f"写入日志失败: {str(e)}")


def backup_and_upload_with_retry(pdf_path: str, oss_file_name: str, max_retries: int = 3):
    """
    备份文件到本地并上传到OSS，支持重试机制
    
    Args:
        pdf_path: PDF文件路径
        oss_file_name: OSS文件名
        max_retries: 最大重试次数
    
    Returns:
        tuple: (success: bool, local_path: str, file_size: int, error_msg: str)
    """
    import os
    import shutil
    import time
    
    # 1. 首先备份到本地
    local_dir = ensure_local_directory()
    local_filename = os.path.basename(oss_file_name)
    local_path = os.path.join(local_dir, local_filename)
    
    # 获取原始文件大小
    file_size = get_file_size(pdf_path)
    
    try:
        # 复制文件到本地
        shutil.copy2(pdf_path, local_path)
        log_upload_operation("LOCAL_BACKUP", local_path, True)
        print(f"文件已备份到本地: {local_path} (大小: {file_size} 字节)")
    except Exception as e:
        error_msg = f"本地备份失败: {str(e)}"
        log_upload_operation("LOCAL_BACKUP", local_path, False, error_msg)
        return False, local_path, file_size, error_msg
    
    # 2. 尝试上传到OSS，支持重试
    last_error = None
    retry_delays = [1, 3, 5]  # 重试间隔（秒）
    
    for attempt in range(max_retries):
        try:
            print(f"尝试上传到OSS (第{attempt + 1}次)...")
            
            upload_file_to_oss_nosdk(
                access_key_id='LTAI5tJy1axoohNuyDZDVdi3',
                access_key_secret='KMC6Ebvn0SyUc3WFGuJbnPLaiveezh',
                bucket_name='landiwulian',
                endpoint='oss-cn-shenzhen.aliyuncs.com',
                object_name=oss_file_name,
                file_path=pdf_path
            )
            
            log_upload_operation("OSS_UPLOAD", oss_file_name, True)
            print(f"文件已成功上传至OSS: {oss_file_name}")
            return True, local_path, file_size, None
            
        except Exception as e:
            last_error = str(e)
            error_msg = f"OSS上传失败 (第{attempt + 1}次): {last_error}"
            print(error_msg)
            log_upload_operation("OSS_UPLOAD", oss_file_name, False, error_msg)
            
            # 如果不是最后一次尝试，等待后重试
            if attempt < max_retries - 1:
                delay = retry_delays[min(attempt, len(retry_delays) - 1)]
                print(f"等待{delay}秒后重试...")
                time.sleep(delay)
    
    # 所有重试都失败了
    final_error = f"OSS上传失败，已重试{max_retries}次。最后错误: {last_error}"
    print(final_error)
    print(f"文件已保存到本地: {local_path}")
    
    return False, local_path, file_size, final_error


def md_to_pdf_and_upload(md_content: str, oss_file_name: str):
    """
    改进版PDF生成和上传函数，支持本地备份和重试机制
    
    Args:
        md_content: Markdown内容
        oss_file_name: OSS文件名
    
    Returns:
        str: OSS文件名（兼容原接口）
    
    Raises:
        Exception: 如果PDF生成失败或上传完全失败
    """
    import os
    import tempfile
    
    # 1. Markdown 转 HTML
    try:
        config = pdfkit.configuration(wkhtmltopdf=r'E:\\wkhtmltopdf\bin\wkhtmltopdf.exe')
        html_content = markdown.markdown(md_content, extensions=['tables'])
        log_upload_operation("HTML_CONVERT", f"Content length: {len(html_content)}", True)
    except Exception as e:
        error_msg = f"Markdown转HTML失败: {str(e)}"
        log_upload_operation("HTML_CONVERT", "md_content", False, error_msg)
        raise Exception(error_msg)
    
    # 2. 生成临时PDF文件
    temp_pdf_path = None
    try:
        with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_pdf:
            temp_pdf_path = temp_pdf.name
            
            # 3. HTML 转 PDF
            options = {
                'encoding': 'UTF-8',
                'custom-header': [('Accept-Charset', 'UTF-8')],
                'enable-local-file-access': None  # 允许访问本地字体文件
            }
            
            pdfkit.from_string(
                html_content,
                temp_pdf_path,
                configuration=config,
                options=options
            )
            
            log_upload_operation("PDF_GENERATE", temp_pdf_path, True)
            print(f"PDF文件已生成: {temp_pdf_path}")
    
    except Exception as e:
        error_msg = f"PDF生成失败: {str(e)}"
        log_upload_operation("PDF_GENERATE", temp_pdf_path or "unknown", False, error_msg)
        # 清理临时文件
        if temp_pdf_path and os.path.exists(temp_pdf_path):
            try:
                os.unlink(temp_pdf_path)
            except:
                pass
        raise Exception(error_msg)
    
    # 4. 备份到本地并上传到OSS（支持重试）
    try:
        upload_success, local_path, file_size, upload_error = backup_and_upload_with_retry(
            temp_pdf_path, oss_file_name, max_retries=3
        )
        
        # 5. 清理临时文件
        try:
            os.unlink(temp_pdf_path)
        except Exception as e:
            print(f"清理临时文件失败: {str(e)}")
        
        # 6. 处理结果
        if upload_success:
            print(f"文件处理完成: OSS上传成功，本地备份: {local_path}")
            return oss_file_name
        else:
            print(f"OSS上传失败，但文件已保存到本地: {local_path}")
            print(f"错误信息: {upload_error}")
            # 即使上传失败，也返回oss_file_name保持接口兼容性
            # 但会在日志中记录失败信息
            return oss_file_name
            
    except Exception as e:
        # 确保清理临时文件
        if temp_pdf_path and os.path.exists(temp_pdf_path):
            try:
                os.unlink(temp_pdf_path)
            except:
                pass
        
        error_msg = f"文件处理失败: {str(e)}"
        log_upload_operation("FILE_PROCESS", oss_file_name, False, error_msg)
        raise Exception(error_msg)


def analyze_health_data_structure(df_employee_info, df_health_exception):
    """
    分析健康数据维度，决定报告类型
    
    Args:
        df_employee_info: 员工信息数据DataFrame
        df_health_exception: 健康异常数据DataFrame
    
    Returns:
        dict: 包含报告类型和维度信息的字典
    """
    if df_employee_info.empty or df_health_exception.empty:
        return {
            "report_type": "no_data",
            "focus": "无数据",
            "department_count": 0,
            "employee_count": 0,
            "exception_count": 0,
            "departments": [],
            "data_types": []
        }
    
    department_count = df_employee_info['departName'].nunique()
    employee_count = len(df_employee_info)
    exception_count = len(df_health_exception)
    
    # 获取具体的部门名称和数据类型
    departments = df_employee_info['departName'].unique().tolist()
    data_types = df_health_exception['dataType'].unique().tolist() if not df_health_exception.empty else []
    
    # 判断报告类型
    if department_count == 1:
        report_type = "single_department"  # 单部门：员工间对比
        focus = "员工健康横向对比分析"
    elif department_count > 1:
        report_type = "multi_department"   # 多部门：部门间对比
        focus = "部门健康横向对比分析"
    else:
        report_type = "general"
        focus = "综合健康分析"
    
    return {
        "report_type": report_type,
        "focus": focus,
        "department_count": department_count,
        "employee_count": employee_count,
        "exception_count": exception_count,
        "departments": departments,
        "data_types": data_types
    }


def analyze_heart_rate_intensity_correlation(df_merged):
    """
    分析心率与劳动强度的关联性 - 核心健康分析逻辑
    
    Args:
        df_merged: 合并后的健康数据和员工信息
    
    Returns:
        dict: 心率强度关联分析结果
    """
    if df_merged.empty:
        return {
            "correlation_analysis": [],
            "intensity_groups": {},
            "risk_assessment": [],
            "recommendations": []
        }
    
    # 过滤心率数据
    heart_rate_data = df_merged[df_merged['dataType'] == '心率'].copy()
    
    if heart_rate_data.empty:
        return {
            "correlation_analysis": [],
            "intensity_groups": {},
            "risk_assessment": [],
            "recommendations": []
        }
    
    # 按劳动强度分组分析心率异常的合理性
    intensity_groups = {}
    
    for intensity in [1, 2, 3, 4, 5]:  # 劳动强度等级
        group_data = heart_rate_data[heart_rate_data['intensity'] == intensity]
        if len(group_data) == 0:
            continue
            
        # 分析该强度下的心率分布
        avg_heart_rate = group_data['healthValue'].mean()
        exception_count = len(group_data[group_data['exception_level'] >= 2])
        total_count = len(group_data)
        exception_rate = exception_count / total_count if total_count > 0 else 0
        
        # 根据劳动强度评估心率异常的合理性
        expected_heart_rate_range = {
            1: (60, 80),   # 低强度
            2: (70, 90),   # 轻度
            3: (80, 110),  # 中度
            4: (90, 130),  # 高强度
            5: (100, 150)  # 极高强度
        }
        
        min_hr, max_hr = expected_heart_rate_range.get(intensity, (60, 100))
        
        # 评估异常是否合理
        reasonable_exceptions = 0
        unreasonable_exceptions = 0
        
        for _, row in group_data.iterrows():
            hr = row['healthValue']
            exception_level = row['exception_level']
            
            if exception_level >= 2:  # 有异常
                if hr > max_hr or hr < min_hr:
                    if (intensity >= 3 and hr > max_hr) or (intensity <= 2 and hr < min_hr):
                        reasonable_exceptions += 1  # 高强度时心率高，或低强度时心率低，相对合理
                    else:
                        unreasonable_exceptions += 1  # 需要关注的异常
                else:
                    unreasonable_exceptions += 1  # 在正常范围内却有异常，需要关注
        
        intensity_groups[f"强度{intensity}级"] = {
            "数据量": total_count,
            "平均心率": round(avg_heart_rate, 1),
            "异常次数": exception_count,
            "异常率": round(exception_rate * 100, 1),
            "合理异常": reasonable_exceptions,
            "需关注异常": unreasonable_exceptions,
            "期望心率范围": f"{min_hr}-{max_hr}",
            "风险等级": "低" if unreasonable_exceptions == 0 else "中" if unreasonable_exceptions <= total_count * 0.1 else "高"
        }
    
    # 生成关联分析
    correlation_analysis = []
    for intensity_level, stats in intensity_groups.items():
        if stats["需关注异常"] > 0:
            correlation_analysis.append({
                "劳动强度": intensity_level,
                "分析结果": f"在{stats['数据量']}次记录中，发现{stats['需关注异常']}次需要关注的心率异常",
                "建议": "建议重点关注该强度下的员工心率状况" if stats["需关注异常"] > stats["数据量"] * 0.1 else "异常情况在可控范围内"
            })
    
    return {
        "correlation_analysis": correlation_analysis,
        "intensity_groups": intensity_groups,
        "total_heart_rate_records": len(heart_rate_data),
        "overall_risk_level": "高" if any(g["风险等级"] == "高" for g in intensity_groups.values()) else "中" if any(g["风险等级"] == "中" for g in intensity_groups.values()) else "低"
    }


def calculate_complete_health_data(df_employee_info, df_health_exception, start_time, end_time, total_days, member_name):
    """
    核心健康统计计算函数 - 标准化数据结构输出
    完全模仿 calculate_complete_report_data 的架构
    
    Args:
        df_employee_info: 员工信息数据
        df_health_exception: 健康异常数据
        start_time: 开始时间
        end_time: 结束时间
        total_days: 总天数
        member_name: 机构名称
    
    Returns:
        dict: 标准化的完整健康统计数据
    """
    print(f"📊 开始健康数据统计计算...")
    print(f"👥 员工信息数据: {len(df_employee_info)} 条")
    print(f"🏥 健康异常数据: {len(df_health_exception)} 条")
    
    # 1. 数据预处理和合并
    if df_health_exception.empty:
        print("ℹ️ 无健康异常数据，生成正常报告")
        return {
            "report_info": {
                "type": "no_exceptions",
                "focus": "健康状况良好",
                "member_name": member_name,
                "period_days": total_days
            },
            "basic_info": {
                "total_employees": len(df_employee_info),
                "total_departments": df_employee_info['departName'].nunique() if not df_employee_info.empty else 0,
                "exception_count": 0,
                "data_types": []
            },
            "statistics": {},
            "rankings": {},
            "analysis_results": {}
        }
    
    # 通过IMEI关联数据
    df_merged = pd.merge(df_health_exception, df_employee_info, on="imei", how="left")
    print(f"🔗 数据关联结果: {len(df_merged)} 条记录")
    print(f"🔗 涉及员工: {df_merged['nickName'].nunique()} 人")
    
    # 2. 分析数据维度
    data_structure = analyze_health_data_structure(df_employee_info, df_health_exception)
    
    # 3. 异常等级分布统计
    exception_level_stats = df_merged.groupby(['exception_level', 'dataType']).agg({
        'imei': 'count',
        'nickName': 'nunique'
    }).reset_index()
    exception_level_stats.columns = ['异常等级', '数据类型', '异常次数', '涉及人数']
    
    # 4. 按员工统计异常情况
    employee_stats = df_merged.groupby(['imei', 'nickName', 'departName']).agg({
        'exception_level': ['count', 'max', 'mean'],
        'dataType': lambda x: list(x.unique()),
        'intensity': 'mean',
        'step_8_min': 'mean'
    }).round(2)
    employee_stats.columns = ['异常总次数', '最高异常等级', '平均异常等级', '异常类型', '平均劳动强度', '平均运动步数']
    employee_stats = employee_stats.reset_index()
    
    # 5. 按部门统计
    department_stats = df_merged.groupby('departName').agg({
        'imei': 'nunique',
        'exception_level': ['count', 'mean'],
        'nickName': 'nunique'
    }).round(2)
    department_stats.columns = ['异常设备数', '异常总次数', '平均异常等级', '异常人数']
    department_stats = department_stats.reset_index()
    
    # 6. 按数据类型统计
    data_type_stats = df_merged.groupby('dataType').agg({
        'imei': 'nunique',
        'exception_level': ['count', 'mean', 'max'],
        'nickName': 'nunique'
    }).round(2)
    data_type_stats.columns = ['异常设备数', '异常次数', '平均异常等级', '最高异常等级', '异常人数']
    data_type_stats = data_type_stats.reset_index()
    
    # 7. 心率与劳动强度关联分析（核心功能）
    print("🫀 开始心率与劳动强度关联分析...")
    heart_rate_analysis = analyze_heart_rate_intensity_correlation(df_merged)
    
    # 8. 员工健康风险分级
    employee_risk_levels = []
    for _, emp in employee_stats.iterrows():
        risk_score = 0
        
        # 异常次数权重
        if emp['异常总次数'] >= 10:
            risk_score += 3
        elif emp['异常总次数'] >= 5:
            risk_score += 2
        elif emp['异常总次数'] >= 2:
            risk_score += 1
        
        # 最高异常等级权重
        if emp['最高异常等级'] >= 4:
            risk_score += 3
        elif emp['最高异常等级'] >= 3:
            risk_score += 2
        elif emp['最高异常等级'] >= 2:
            risk_score += 1
        
        # 平均异常等级权重
        if emp['平均异常等级'] >= 3:
            risk_score += 2
        elif emp['平均异常等级'] >= 2.5:
            risk_score += 1
        
        # 确定风险等级
        if risk_score >= 6:
            risk_level = "紧急"
        elif risk_score >= 4:
            risk_level = "预警"
        elif risk_score >= 2:
            risk_level = "关注"
        else:
            risk_level = "正常"
        
        employee_risk_levels.append({
            "姓名": emp['nickName'],
            "部门": emp['departName'],
            "风险等级": risk_level,
            "风险评分": risk_score,
            "异常次数": emp['异常总次数'],
            "最高异常等级": emp['最高异常等级']
        })
    
    # 按风险等级排序
    employee_risk_levels.sort(key=lambda x: x['风险评分'], reverse=True)
    
    # 9. 时间趋势分析
    df_merged['日期'] = pd.to_datetime(df_merged['createDate']).dt.date
    daily_stats = df_merged.groupby('日期').agg({
        'exception_level': ['count', 'mean'],
        'nickName': 'nunique'
    }).round(2)
    daily_stats.columns = ['异常次数', '平均异常等级', '异常人数']
    daily_stats = daily_stats.reset_index()
    
    # 10. 智能排名计算
    rankings = {}
    
    # 员工风险排名
    if len(employee_risk_levels) > 0:
        high_risk_employees = [emp for emp in employee_risk_levels if emp['风险等级'] in ['紧急', '预警']]
        normal_employees = [emp for emp in employee_risk_levels if emp['风险等级'] == '正常']
        
        rankings["high_risk_employees"] = high_risk_employees[:10]  # 前10名高风险
        rankings["normal_employees"] = normal_employees[:5]  # 前5名正常员工
        rankings["show_employee_rankings"] = True
    
    # 部门排名（如果有多个部门）
    if len(department_stats) > 1:
        department_stats['风险指数'] = (department_stats['平均异常等级'] * department_stats['异常总次数'] / department_stats['异常人数']).round(2)
        top_risk_departments = department_stats.nlargest(3, '风险指数').to_dict('records')
        low_risk_departments = department_stats.nsmallest(3, '风险指数').to_dict('records')
        
        rankings["top_risk_departments"] = top_risk_departments
        rankings["low_risk_departments"] = low_risk_departments
        rankings["show_department_rankings"] = True
    
    # 数据类型风险排名
    if len(data_type_stats) > 1:
        data_type_stats['风险指数'] = (data_type_stats['平均异常等级'] * data_type_stats['异常次数']).round(2)
        top_risk_data_types = data_type_stats.nlargest(3, '风险指数').to_dict('records')
        
        rankings["top_risk_data_types"] = top_risk_data_types
        rankings["show_data_type_rankings"] = True
    
    # 11. 构建完整统计结果
    complete_stats = {
        "report_info": {
            "type": data_structure["report_type"],
            "focus": data_structure["focus"],
            "member_name": member_name,
            "period_days": total_days,
            "generation_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        },
        
        "basic_info": {
            "total_employees": len(df_employee_info),
            "exception_employees": df_merged['nickName'].nunique(),
            "total_departments": data_structure["department_count"],
            "exception_count": len(df_health_exception),
            "data_types": data_structure["data_types"],
            "departments": data_structure["departments"]
        },
        
        "statistics": {
            "exception_level_distribution": exception_level_stats.to_dict('records'),
            "employee_statistics": employee_stats.to_dict('records'),
            "department_statistics": department_stats.to_dict('records'),
            "data_type_statistics": data_type_stats.to_dict('records'),
            "daily_trend": daily_stats.to_dict('records'),
            "employee_risk_levels": employee_risk_levels
        },
        
        "rankings": rankings,
        
        "analysis_results": {
            "heart_rate_intensity_analysis": heart_rate_analysis,
            "overall_health_score": calculate_overall_health_score(employee_risk_levels),
            "key_findings": generate_key_health_findings(df_merged, employee_risk_levels, heart_rate_analysis)
        }
    }
    
    print(f"✅ 健康数据统计计算完成")
    print(f"📋 涉及 {complete_stats['basic_info']['exception_employees']} 名员工")
    print(f"🏥 {complete_stats['basic_info']['exception_count']} 条异常记录")
    print(f"⚠️ {len([emp for emp in employee_risk_levels if emp['风险等级'] in ['紧急', '预警']])} 名高风险员工")
    
    return complete_stats


def calculate_overall_health_score(employee_risk_levels):
    """计算整体健康评分"""
    if not employee_risk_levels:
        return {"score": 100, "level": "优秀"}
    
    total_employees = len(employee_risk_levels)
    emergency_count = len([emp for emp in employee_risk_levels if emp['风险等级'] == '紧急'])
    warning_count = len([emp for emp in employee_risk_levels if emp['风险等级'] == '预警'])
    attention_count = len([emp for emp in employee_risk_levels if emp['风险等级'] == '关注'])
    normal_count = len([emp for emp in employee_risk_levels if emp['风险等级'] == '正常'])
    
    # 计算健康评分（100分制）
    score = 100 - (emergency_count * 30 + warning_count * 20 + attention_count * 10) / total_employees
    score = max(0, min(100, score))
    
    # 确定等级
    if score >= 90:
        level = "优秀"
    elif score >= 80:
        level = "良好"
    elif score >= 70:
        level = "一般"
    elif score >= 60:
        level = "较差"
    else:
        level = "差"
    
    return {
        "score": round(score, 1),
        "level": level,
        "distribution": {
            "紧急": emergency_count,
            "预警": warning_count,
            "关注": attention_count,
            "正常": normal_count
        }
    }


def generate_key_health_findings(df_merged, employee_risk_levels, heart_rate_analysis):
    """生成关键健康发现"""
    findings = []
    
    # 高风险员工发现
    high_risk_count = len([emp for emp in employee_risk_levels if emp['风险等级'] in ['紧急', '预警']])
    if high_risk_count > 0:
        findings.append(f"发现 {high_risk_count} 名高风险员工需要重点关注")
    
    # 心率强度分析发现
    if heart_rate_analysis.get("overall_risk_level") == "高":
        findings.append("心率与劳动强度分析显示存在高风险情况")
    
    # 异常类型发现
    data_type_counts = df_merged['dataType'].value_counts()
    if len(data_type_counts) > 0:
        most_common = data_type_counts.index[0]
        findings.append(f"{most_common}异常最为常见，共 {data_type_counts.iloc[0]} 次")
    
    # 异常等级发现
    high_level_exceptions = len(df_merged[df_merged['exception_level'] >= 3])
    if high_level_exceptions > 0:
        findings.append(f"发现 {high_level_exceptions} 次中度及以上异常，需要及时处理")
    
    return findings


def generate_health_report_tables(complete_stats):
    """
    生成健康报告的HTML表格内容
    完全模仿 generate_report_tables 的设计
    
    Args:
        complete_stats: 完整的健康统计数据
    
    Returns:
        dict: 包含各种表格的HTML内容
    """
    print("📋 开始生成健康报告HTML表格...")
    
    report_tables = {}
    
    # 1. 基础信息表
    basic_info = complete_stats["basic_info"]
    basic_info_html = f"""
    <div class="table-container">
        <h3 class="table-title">基础信息概览</h3>
        <table class="data-table">
            <thead>
                <tr>
                    <th>项目</th>
                    <th>数值</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>员工总数</td>
                    <td>{basic_info['total_employees']} 人</td>
                </tr>
                <tr>
                    <td>异常员工数</td>
                    <td>{basic_info['exception_employees']} 人</td>
                </tr>
                <tr>
                    <td>部门数量</td>
                    <td>{basic_info['total_departments']} 个</td>
                </tr>
                <tr>
                    <td>异常记录总数</td>
                    <td>{basic_info['exception_count']} 条</td>
                </tr>
                <tr>
                    <td>涉及数据类型</td>
                    <td>{', '.join(basic_info['data_types'])}</td>
                </tr>
            </tbody>
        </table>
    </div>
    """
    report_tables["basic_info"] = basic_info_html
    
    # 2. 整体健康评分表
    health_score = complete_stats["analysis_results"]["overall_health_score"]
    health_score_html = f"""
    <div class="table-container">
        <h3 class="table-title">整体健康评分</h3>
        <table class="data-table">
            <thead>
                <tr>
                    <th>评分项目</th>
                    <th>数值</th>
                </tr>
            </thead>
            <tbody>
                <tr class="{'score-excellent' if health_score['score'] >= 90 else 'score-good' if health_score['score'] >= 80 else 'score-warning' if health_score['score'] >= 60 else 'score-danger'}">
                    <td><strong>健康评分</strong></td>
                    <td><strong>{health_score['score']} 分 ({health_score['level']})</strong></td>
                </tr>
                <tr>
                    <td>正常员工</td>
                    <td>{health_score['distribution']['正常']} 人</td>
                </tr>
                <tr>
                    <td>关注员工</td>
                    <td>{health_score['distribution']['关注']} 人</td>
                </tr>
                <tr class="warning-row">
                    <td>预警员工</td>
                    <td>{health_score['distribution']['预警']} 人</td>
                </tr>
                <tr class="danger-row">
                    <td>紧急员工</td>
                    <td>{health_score['distribution']['紧急']} 人</td>
                </tr>
            </tbody>
        </table>
    </div>
    """
    report_tables["health_score"] = health_score_html
    
    # 3. 异常等级分布表
    exception_level_stats = complete_stats["statistics"]["exception_level_distribution"]
    if exception_level_stats:
        exception_level_html = """
        <div class="table-container">
            <h3 class="table-title">异常等级分布统计</h3>
            <table class="data-table">
                <thead>
                    <tr>
                        <th>异常等级</th>
                        <th>数据类型</th>
                        <th>异常次数</th>
                        <th>涉及人数</th>
                    </tr>
                </thead>
                <tbody>
        """
        
        for stat in exception_level_stats:
            level_class = ""
            if stat['异常等级'] >= 4:
                level_class = "danger-row"
            elif stat['异常等级'] >= 3:
                level_class = "warning-row"
            elif stat['异常等级'] >= 2:
                level_class = "attention-row"
            
            exception_level_html += f"""
                    <tr class="{level_class}">
                        <td>{stat['异常等级']}级</td>
                        <td>{stat['数据类型']}</td>
                        <td>{stat['异常次数']}</td>
                        <td>{stat['涉及人数']}</td>
                    </tr>
            """
        
        exception_level_html += """
                </tbody>
            </table>
        </div>
        """
        report_tables["exception_level_distribution"] = exception_level_html
    
    # 4. 员工风险排名表
    rankings = complete_stats["rankings"]
    if rankings.get("show_employee_rankings") and rankings.get("high_risk_employees"):
        high_risk_html = """
        <div class="table-container">
            <h3 class="table-title">高风险员工排名</h3>
            <table class="data-table">
                <thead>
                    <tr>
                        <th>排名</th>
                        <th>姓名</th>
                        <th>部门</th>
                        <th>风险等级</th>
                        <th>风险评分</th>
                        <th>异常次数</th>
                        <th>最高异常等级</th>
                    </tr>
                </thead>
                <tbody>
        """
        
        for idx, emp in enumerate(rankings["high_risk_employees"], 1):
            risk_class = ""
            if emp['风险等级'] == "紧急":
                risk_class = "danger-row"
            elif emp['风险等级'] == "预警":
                risk_class = "warning-row"
            elif emp['风险等级'] == "关注":
                risk_class = "attention-row"
            
            high_risk_html += f"""
                    <tr class="{risk_class}">
                        <td>{idx}</td>
                        <td>{emp['姓名']}</td>
                        <td>{emp['部门']}</td>
                        <td><strong>{emp['风险等级']}</strong></td>
                        <td>{emp['风险评分']}</td>
                        <td>{emp['异常次数']}</td>
                        <td>{emp['最高异常等级']}</td>
                    </tr>
            """
        
        high_risk_html += """
                </tbody>
            </table>
        </div>
        """
        report_tables["high_risk_employees"] = high_risk_html
    
    # 5. 心率与劳动强度关联分析表
    heart_rate_analysis = complete_stats["analysis_results"]["heart_rate_intensity_analysis"]
    if heart_rate_analysis.get("intensity_groups"):
        heart_rate_html = f"""
        <div class="table-container">
            <h3 class="table-title">心率与劳动强度关联分析</h3>
            <div class="analysis-summary">
                <p><strong>总心率记录数：</strong>{heart_rate_analysis['total_heart_rate_records']} 条</p>
                <p><strong>整体风险等级：</strong><span class="{'risk-high' if heart_rate_analysis['overall_risk_level'] == '高' else 'risk-medium' if heart_rate_analysis['overall_risk_level'] == '中' else 'risk-low'}">{heart_rate_analysis['overall_risk_level']}</span></p>
            </div>
            <table class="data-table">
                <thead>
                    <tr>
                        <th>劳动强度</th>
                        <th>数据量</th>
                        <th>平均心率</th>
                        <th>异常次数</th>
                        <th>异常率(%)</th>
                        <th>合理异常</th>
                        <th>需关注异常</th>
                        <th>期望心率范围</th>
                        <th>风险等级</th>
                    </tr>
                </thead>
                <tbody>
        """
        
        for intensity_level, stats in heart_rate_analysis["intensity_groups"].items():
            risk_class = ""
            if stats['风险等级'] == "高":
                risk_class = "danger-row"
            elif stats['风险等级'] == "中":
                risk_class = "warning-row"
            
            heart_rate_html += f"""
                    <tr class="{risk_class}">
                        <td>{intensity_level}</td>
                        <td>{stats['数据量']}</td>
                        <td>{stats['平均心率']} bpm</td>
                        <td>{stats['异常次数']}</td>
                        <td>{stats['异常率']}%</td>
                        <td>{stats['合理异常']}</td>
                        <td><strong>{stats['需关注异常']}</strong></td>
                        <td>{stats['期望心率范围']} bpm</td>
                        <td><span class="risk-{stats['风险等级']}">{stats['风险等级']}</span></td>
                    </tr>
            """
        
        heart_rate_html += """
                </tbody>
            </table>
        </div>
        """
        report_tables["heart_rate_intensity_analysis"] = heart_rate_html
    
    # 6. 部门健康统计表
    department_stats = complete_stats["statistics"]["department_statistics"]
    if department_stats:
        department_html = """
        <div class="table-container">
            <h3 class="table-title">部门健康统计</h3>
            <table class="data-table">
                <thead>
                    <tr>
                        <th>部门名称</th>
                        <th>异常设备数</th>
                        <th>异常总次数</th>
                        <th>平均异常等级</th>
                        <th>异常人数</th>
                    </tr>
                </thead>
                <tbody>
        """
        
        for dept in department_stats:
            dept_class = ""
            if dept['平均异常等级'] >= 3:
                dept_class = "danger-row"
            elif dept['平均异常等级'] >= 2.5:
                dept_class = "warning-row"
            elif dept['平均异常等级'] >= 2:
                dept_class = "attention-row"
            
            department_html += f"""
                    <tr class="{dept_class}">
                        <td>{dept['departName']}</td>
                        <td>{dept['异常设备数']}</td>
                        <td>{dept['异常总次数']}</td>
                        <td>{dept['平均异常等级']}</td>
                        <td>{dept['异常人数']}</td>
                    </tr>
            """
        
        department_html += """
                </tbody>
            </table>
        </div>
        """
        report_tables["department_statistics"] = department_html
    
    # 7. 数据类型异常统计表
    data_type_stats = complete_stats["statistics"]["data_type_statistics"]
    if data_type_stats:
        data_type_html = """
        <div class="table-container">
            <h3 class="table-title">数据类型异常统计</h3>
            <table class="data-table">
                <thead>
                    <tr>
                        <th>数据类型</th>
                        <th>异常设备数</th>
                        <th>异常次数</th>
                        <th>平均异常等级</th>
                        <th>最高异常等级</th>
                        <th>异常人数</th>
                    </tr>
                </thead>
                <tbody>
        """
        
        for data_type in data_type_stats:
            type_class = ""
            if data_type['最高异常等级'] >= 4:
                type_class = "danger-row"
            elif data_type['最高异常等级'] >= 3:
                type_class = "warning-row"
            elif data_type['平均异常等级'] >= 2.5:
                type_class = "attention-row"
            
            data_type_html += f"""
                    <tr class="{type_class}">
                        <td><strong>{data_type['dataType']}</strong></td>
                        <td>{data_type['异常设备数']}</td>
                        <td>{data_type['异常次数']}</td>
                        <td>{data_type['平均异常等级']}</td>
                        <td>{data_type['最高异常等级']}</td>
                        <td>{data_type['异常人数']}</td>
                    </tr>
            """
        
        data_type_html += """
                </tbody>
            </table>
        </div>
        """
        report_tables["data_type_statistics"] = data_type_html
    
    # 8. 关键发现总结表
    key_findings = complete_stats["analysis_results"]["key_findings"]
    if key_findings:
        findings_html = """
        <div class="table-container">
            <h3 class="table-title">关键发现总结</h3>
            <div class="findings-list">
                <ul>
        """
        
        for finding in key_findings:
            findings_html += f"<li>{finding}</li>"
        
        findings_html += """
                </ul>
            </div>
        </div>
        """
        report_tables["key_findings"] = findings_html
    
    print(f"✅ HTML表格生成完成，共生成 {len(report_tables)} 个表格")
    return report_tables


async def generate_health_ai_analysis_from_tables(report_tables, complete_stats, member_name, start_time, end_time):
    """
    基于已生成的表格内容进行AI分析
    完全模仿 generate_ai_analysis_from_tables 的设计
    
    Args:
        report_tables: 生成的HTML表格内容
        complete_stats: 完整统计数据
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: AI分析结果
    """
    print("🤖 开始基于表格生成AI分析内容...")
    
    # 构建专业的健康分析prompt
    report_info = complete_stats["report_info"]
    basic_info = complete_stats["basic_info"]
    analysis_results = complete_stats["analysis_results"]
    
    # 准备表格内容给AI分析
    tables_content = ""
    
    # 基础信息表格
    if "basic_info" in report_tables:
        tables_content += "\n## 基础信息概览\n"
        tables_content += f"- 员工总数：{basic_info['total_employees']} 人\n"
        tables_content += f"- 异常员工数：{basic_info['exception_employees']} 人\n"
        tables_content += f"- 部门数量：{basic_info['total_departments']} 个\n"
        tables_content += f"- 异常记录总数：{basic_info['exception_count']} 条\n"
        tables_content += f"- 涉及数据类型：{', '.join(basic_info['data_types'])}\n"
    
    # 整体健康评分
    health_score = analysis_results["overall_health_score"]
    tables_content += f"\n## 整体健康评分\n"
    tables_content += f"- 健康评分：{health_score['score']} 分 ({health_score['level']})\n"
    tables_content += f"- 正常员工：{health_score['distribution']['正常']} 人\n"
    tables_content += f"- 关注员工：{health_score['distribution']['关注']} 人\n"
    tables_content += f"- 预警员工：{health_score['distribution']['预警']} 人\n"
    tables_content += f"- 紧急员工：{health_score['distribution']['紧急']} 人\n"
    
    # 异常等级分布统计
    if complete_stats["statistics"]["exception_level_distribution"]:
        tables_content += "\n## 异常等级分布统计\n"
        for stat in complete_stats["statistics"]["exception_level_distribution"]:
            tables_content += f"- {stat['异常等级']}级 {stat['数据类型']}：{stat['异常次数']}次，涉及{stat['涉及人数']}人\n"
    
    # 心率与劳动强度关联分析
    heart_rate_analysis = analysis_results["heart_rate_intensity_analysis"]
    if heart_rate_analysis.get("intensity_groups"):
        tables_content += f"\n## 心率与劳动强度关联分析\n"
        tables_content += f"- 总心率记录数：{heart_rate_analysis['total_heart_rate_records']} 条\n"
        tables_content += f"- 整体风险等级：{heart_rate_analysis['overall_risk_level']}\n"
        
        for intensity_level, stats in heart_rate_analysis["intensity_groups"].items():
            tables_content += f"- {intensity_level}：数据量{stats['数据量']}，平均心率{stats['平均心率']}bpm，需关注异常{stats['需关注异常']}次，风险等级{stats['风险等级']}\n"
    
    # 高风险员工排名
    rankings = complete_stats["rankings"]
    if rankings.get("high_risk_employees"):
        tables_content += "\n## 高风险员工排名（前5名）\n"
        for idx, emp in enumerate(rankings["high_risk_employees"][:5], 1):
            tables_content += f"{idx}. {emp['姓名']}（{emp['部门']}）- 风险等级：{emp['风险等级']}，异常次数：{emp['异常次数']}\n"
    
    # 部门健康统计
    if complete_stats["statistics"]["department_statistics"]:
        tables_content += "\n## 部门健康统计\n"
        for dept in complete_stats["statistics"]["department_statistics"]:
            tables_content += f"- {dept['departName']}：异常人数{dept['异常人数']}人，异常总次数{dept['异常总次数']}次，平均异常等级{dept['平均异常等级']}\n"
    
    # 数据类型异常统计
    if complete_stats["statistics"]["data_type_statistics"]:
        tables_content += "\n## 数据类型异常统计\n"
        for data_type in complete_stats["statistics"]["data_type_statistics"]:
            tables_content += f"- {data_type['dataType']}：异常次数{data_type['异常次数']}次，异常人数{data_type['异常人数']}人，平均异常等级{data_type['平均异常等级']}\n"
    
    # 关键发现
    key_findings = analysis_results["key_findings"]
    if key_findings:
        tables_content += "\n## 关键发现\n"
        for finding in key_findings:
            tables_content += f"- {finding}\n"
    
    # 构建完整的AI分析prompt
    prompt = f"""
你是一名专业的职业健康分析师，请基于以下员工健康监测数据生成专业的健康分析报告。

## 报告基本信息
- 机构名称：{member_name}
- 分析时间：{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}
- 报告类型：{report_info['focus']}
- 分析期间：{report_info['period_days']} 天

## 已计算的统计数据
{tables_content}

## 分析要求
请基于以上**已经准确计算好的数据**，生成专业的健康分析报告，包含以下内容：

### 1. 健康状况总体评估
- 基于整体健康评分进行总体评价
- 分析员工健康风险分布情况
- 识别主要健康风险点

### 2. 重点关注人群分析
- 分析高风险员工的特征和分布
- 评估紧急和预警人员的健康状况
- 提供针对性的健康管理建议

### 3. 心率与劳动强度专业分析
- 基于心率与劳动强度关联数据进行医学分析
- 评估不同劳动强度下心率异常的合理性
- 识别需要医学关注的心率异常模式

### 4. 异常类型专业解读
- 分析各类健康指标（血氧、血压、体温、心率）的异常分布
- 解释不同异常等级的医学意义
- 评估各类异常的紧急程度

### 5. 部门健康状况对比
- 分析各部门员工健康状况差异
- 识别健康管理需要重点关注的部门
- 分析可能的职业健康风险因素

### 6. 管理建议和改进措施
- 提供具体的健康管理改进建议
- 针对高风险员工提出具体措施
- 建议健康监测频率和关注重点
- 提出预防性健康管理措施

## 输出要求
1. 语言专业准确，适合企业管理层阅读
2. 分析基于提供的准确数据，不要自行计算
3. 突出关键健康风险和管理要点
4. 提供可操作的具体建议
5. 无AI生成痕迹，直接面向客户
6. 重点强调心率与劳动强度的医学关联性
7. 不要包含任何（注：XXX）类型的解释性文字
8. 分析结论要有医学依据和实用价值

请生成完整的专业健康分析内容。
"""
    
    # 调用AI生成分析
    try:
        ai_analysis = await invoke_openai_only_result(prompt)
        print(f"✅ AI健康分析生成完成，长度: {len(ai_analysis)} 字符")
        return ai_analysis
        
    except Exception as e:
        print(f"❌ AI分析生成失败: {str(e)}")
        # 返回基础分析作为fallback
        fallback_analysis = generate_fallback_health_analysis(complete_stats, member_name, start_time, end_time)
        return fallback_analysis


def generate_fallback_health_analysis(complete_stats, member_name, start_time, end_time):
    """
    生成基础的健康分析内容（当AI调用失败时使用）
    """
    basic_info = complete_stats["basic_info"]
    health_score = complete_stats["analysis_results"]["overall_health_score"]
    key_findings = complete_stats["analysis_results"]["key_findings"]
    
    analysis = f"""
# {member_name} 员工健康状况分析报告

## 报告概览
- **分析时间**: {start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}
- **员工总数**: {basic_info['total_employees']} 人
- **异常员工数**: {basic_info['exception_employees']} 人
- **整体健康评分**: {health_score['score']} 分 ({health_score['level']})

## 健康状况总体评估
在 {basic_info['total_employees']} 名员工中，发现 {basic_info['exception_employees']} 名员工存在健康异常记录，
整体健康评分为 {health_score['score']} 分，评级为"{health_score['level']}"。

## 风险人群分布
- 正常员工：{health_score['distribution']['正常']} 人
- 关注员工：{health_score['distribution']['关注']} 人
- 预警员工：{health_score['distribution']['预警']} 人
- 紧急员工：{health_score['distribution']['紧急']} 人

## 关键发现
"""
    
    for finding in key_findings:
        analysis += f"- {finding}\n"
    
    analysis += """

## 管理建议
1. 重点关注预警和紧急级别员工的健康状况
2. 建立定期健康监测机制
3. 针对高风险员工制定个性化健康管理方案
4. 加强职业健康教育和预防措施
5. 定期评估和调整健康管理策略
"""
    
    return analysis


def render_final_health_report(complete_stats, report_tables, ai_content, member_name, start_time, end_time):
    """
    渲染最终的健康报告HTML内容
    完全模仿 render_final_report 的设计
    
    Args:
        complete_stats: 完整统计数据
        report_tables: HTML表格内容
        ai_content: AI分析内容
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: 完整的HTML报告内容
    """
    print("🎨 开始渲染最终健康报告...")
    
    report_info = complete_stats["report_info"]
    basic_info = complete_stats["basic_info"]
    health_score = complete_stats["analysis_results"]["overall_health_score"]
    
    # 生成报告标题
    report_title = f"{member_name} 员工健康状况分析报告"
    report_subtitle = f"{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}"
    
    # 构建完整的HTML报告
    html_content = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{report_title}</title>
    <style>
        /* 基础样式 */
        body {{
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            line-height: 1.6;
            margin: 0;
            padding: 20px;
            background-color: #f9f9f9;
            color: #333;
        }}
        
        .report-container {{
            max-width: 210mm;
            margin: 0 auto;
            background-color: white;
            padding: 30px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }}
        
        /* 标题样式 */
        .report-header {{
            text-align: center;
            border-bottom: 3px solid #2c5aa0;
            padding-bottom: 20px;
            margin-bottom: 30px;
        }}
        
        .report-title {{
            font-size: 28px;
            font-weight: bold;
            color: #2c5aa0;
            margin: 0 0 10px 0;
        }}
        
        .report-subtitle {{
            font-size: 16px;
            color: #666;
            margin: 0;
        }}
        
        .report-meta {{
            display: flex;
            justify-content: space-between;
            margin-top: 15px;
            font-size: 14px;
            color: #888;
        }}
        
        /* 摘要卡片样式 */
        .summary-cards {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }}
        
        .summary-card {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
        }}
        
        .summary-card.health-score {{
            background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
        }}
        
        .summary-card.warning {{
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
        }}
        
        .summary-card.danger {{
            background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
            color: #333;
        }}
        
        .card-title {{
            font-size: 14px;
            opacity: 0.9;
            margin-bottom: 10px;
        }}
        
        .card-value {{
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 5px;
        }}
        
        .card-label {{
            font-size: 12px;
            opacity: 0.8;
        }}
        
        /* 表格样式 */
        .table-container {{
            margin-bottom: 30px;
            page-break-inside: avoid;
        }}
        
        .table-title {{
            font-size: 18px;
            font-weight: bold;
            color: #2c5aa0;
            margin-bottom: 15px;
            padding-left: 10px;
            border-left: 4px solid #2c5aa0;
        }}
        
        .data-table {{
            width: 100%;
            border-collapse: collapse;
            font-size: 13px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }}
        
        .data-table th {{
            background-color: #2c5aa0;
            color: white;
            padding: 12px 8px;
            text-align: center;
            font-weight: bold;
        }}
        
        .data-table td {{
            padding: 10px 8px;
            text-align: center;
            border-bottom: 1px solid #eee;
        }}
        
        .data-table tbody tr:hover {{
            background-color: #f5f5f5;
        }}
        
        /* 风险等级样式 */
        .danger-row {{
            background-color: #ffebee !important;
        }}
        
        .warning-row {{
            background-color: #fff3e0 !important;
        }}
        
        .attention-row {{
            background-color: #f3e5f5 !important;
        }}
        
        .score-excellent {{
            background-color: #e8f5e8 !important;
            color: #2e7d32 !important;
        }}
        
        .score-good {{
            background-color: #e3f2fd !important;
            color: #1976d2 !important;
        }}
        
        .score-warning {{
            background-color: #fff3e0 !important;
            color: #f57c00 !important;
        }}
        
        .score-danger {{
            background-color: #ffebee !important;
            color: #d32f2f !important;
        }}
        
        /* 风险标签样式 */
        .risk-high {{
            color: #d32f2f;
            font-weight: bold;
        }}
        
        .risk-medium {{
            color: #f57c00;
            font-weight: bold;
        }}
        
        .risk-low {{
            color: #388e3c;
            font-weight: bold;
        }}
        
        /* AI分析内容样式 */
        .ai-analysis {{
            background-color: #f8f9fa;
            padding: 25px;
            border-radius: 10px;
            margin: 30px 0;
            border-left: 5px solid #2c5aa0;
        }}
        
        .ai-analysis h1, .ai-analysis h2, .ai-analysis h3 {{
            color: #2c5aa0;
        }}
        
        .ai-analysis h1 {{
            font-size: 20px;
            margin-top: 0;
        }}
        
        .ai-analysis h2 {{
            font-size: 18px;
            margin-top: 25px;
        }}
        
        .ai-analysis h3 {{
            font-size: 16px;
            margin-top: 20px;
        }}
        
        /* 分析摘要样式 */
        .analysis-summary {{
            background-color: #e3f2fd;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }}
        
        .analysis-summary p {{
            margin: 5px 0;
            font-weight: 500;
        }}
        
        /* 发现列表样式 */
        .findings-list {{
            background-color: #fff;
            padding: 20px;
            border-radius: 8px;
            border: 1px solid #e0e0e0;
        }}
        
        .findings-list ul {{
            margin: 0;
            padding-left: 20px;
        }}
        
        .findings-list li {{
            margin-bottom: 8px;
            line-height: 1.5;
        }}
        
        /* 页面分隔符 */
        .page-break {{
            page-break-before: always;
        }}
        
        /* 打印样式 */
        @media print {{
            body {{
                background-color: white;
            }}
            
            .report-container {{
                box-shadow: none;
                max-width: none;
            }}
        }}
    </style>
</head>
<body>
    <div class="report-container">
        <!-- 报告头部 -->
        <div class="report-header">
            <h1 class="report-title">{report_title}</h1>
            <p class="report-subtitle">{report_subtitle}</p>
            <div class="report-meta">
                <span>报告类型：{report_info['focus']}</span>
                <span>分析期间：{report_info['period_days']} 天</span>
                <span>生成时间：{report_info['generation_time']}</span>
            </div>
        </div>
        
        <!-- 核心指标摘要 -->
        <div class="summary-cards">
            <div class="summary-card health-score">
                <div class="card-title">整体健康评分</div>
                <div class="card-value">{health_score['score']}</div>
                <div class="card-label">{health_score['level']}</div>
            </div>
            <div class="summary-card">
                <div class="card-title">员工总数</div>
                <div class="card-value">{basic_info['total_employees']}</div>
                <div class="card-label">人</div>
            </div>
            <div class="summary-card {'warning' if basic_info['exception_employees'] > 0 else ''}">
                <div class="card-title">异常员工数</div>
                <div class="card-value">{basic_info['exception_employees']}</div>
                <div class="card-label">人</div>
            </div>
            <div class="summary-card {'danger' if health_score['distribution']['紧急'] > 0 else 'warning' if health_score['distribution']['预警'] > 0 else ''}">
                <div class="card-title">高风险员工</div>
                <div class="card-value">{health_score['distribution']['紧急'] + health_score['distribution']['预警']}</div>
                <div class="card-label">人</div>
            </div>
        </div>
        
        <!-- 表格内容 -->
        {report_tables.get('basic_info', '')}
        {report_tables.get('health_score', '')}
        {report_tables.get('exception_level_distribution', '')}
        {report_tables.get('high_risk_employees', '')}
        {report_tables.get('heart_rate_intensity_analysis', '')}
        {report_tables.get('department_statistics', '')}
        {report_tables.get('data_type_statistics', '')}
        {report_tables.get('key_findings', '')}
        
        <!-- AI分析内容 -->
        <div class="page-break"></div>
        <div class="ai-analysis">
            {ai_content}
        </div>
        
        <!-- 报告尾部 -->
        <div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #eee; text-align: center; color: #666; font-size: 12px;">
            <p>本报告由智能健康分析系统生成 | 生成时间：{report_info['generation_time']}</p>
            <p>如需详细分析或有疑问，请联系健康管理部门</p>
        </div>
    </div>
</body>
</html>
"""
    
    print(f"✅ 健康报告HTML渲染完成，长度: {len(html_content)} 字符")
    return html_content


async def get_attendance_rate(df_base, df_work, total_days) -> pd.DataFrame:
    # 按IMEI合并数据（内连接）
    df_all = pd.merge(df_base, df_work, on="imei", how="left")
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    df_all = df_all.fillna({
        "date": pd.NaT,
        "intensity": 0,
        "total_steps": 0,
        "total_time": 0
    })
    # 修正后的聚合逻辑
    # 计算出勤率
    df_clock_in = df_all.groupby("imei").agg(
        工作天数=("date", lambda x: x.nunique())
    ).reset_index()
    df_clock_in["总天数"] = total_days
    # 处理除零错误
    df_clock_in["出勤率"] = df_clock_in.apply(
        lambda row: (row["工作天数"] / row["总天数"] * 100)
        if row["总天数"] != 0 else 0,
        axis=1
    )
    # 计算每天有效工作时间达标率
    df_yx = df_all.groupby(['imei', 'date']).agg(
        daily_steps_sum=('total_steps', 'sum'),
        daily_time_sum=('total_time', 'sum')
    ).reset_index()
    # 定义达标条件
    df_yx['达标'] = df_yx.apply(
        lambda row: 1 if row['daily_steps_sum'] > 8000 and row['daily_time_sum'] > 300 else 0,
        axis=1
    )
    df_statistic = df_yx.groupby("imei").agg(
        达标天数=("达标", lambda x: (x == 1).sum())
    ).reset_index()
    # 将达标情况合并回df_出勤
    df_clock_in = pd.merge(df_clock_in, df_statistic, on='imei', how='left')
    return df_clock_in


def clean_url_path(url: str) -> str:
    """
    清理 URL 路径：
    1. 将 %2F 转换为 /
    2. 删除问号及之后的查询参数
    """
    # 分割问号，保留路径部分（删除查询参数）
    path_part = url.split('?')[0]

    # 解码 URL，自动处理 %2F 转换为 /
    decoded_path = unquote(path_part)

    return decoded_path


def generate_report_tables(complete_stats):
    """
    生成HTML表格内容，为AI分析提供结构化数据
    
    Args:
        complete_stats: 完整的统计数据
    
    Returns:
        dict: 包含各类HTML表格的字典
    """
    tables = {}
    
    # 1. 基础信息表
    tables['basic_info'] = f"""
    <div class="basic-info-section">
        <h3>📋 基础信息</h3>
        <table class="info-table">
            <tr><td>机构名称</td><td>{complete_stats['basic_info']['member_name']}</td></tr>
            <tr><td>统计周期</td><td>{complete_stats['basic_info']['period_start']} 至 {complete_stats['basic_info']['period_end']}</td></tr>
            <tr><td>统计天数</td><td>{complete_stats['basic_info']['period_days']}天</td></tr>
            <tr><td>设备总数</td><td>{complete_stats['basic_info']['total_devices']}台</td></tr>
            <tr><td>区域数量</td><td>{complete_stats['basic_info']['total_regions']}个</td></tr>
            <tr><td>项目数量</td><td>{complete_stats['basic_info']['total_projects']}个</td></tr>
        </table>
    </div>
    """
    
    # 2. 出勤率分析表
    attendance_rate = complete_stats['attendance_analysis']['overall_rate']
    tables['attendance_analysis'] = f"""
    <div class="attendance-section">
        <h3>📊 出勤率分析</h3>
        <table class="data-table">
            <tr><td>整体出勤率</td><td class="{'highlight-good' if attendance_rate > 0.8 else 'highlight-bad'}">{attendance_rate:.1%}</td></tr>
            <tr><td>总应出勤天数</td><td>{complete_stats['attendance_analysis']['total_expected_days']}天</td></tr>
            <tr><td>实际出勤天数</td><td>{complete_stats['attendance_analysis']['total_actual_days']}天</td></tr>
        </table>
    </div>
    """
    
    # 3. 区域出勤率详情表（确保关键表格不被跳过）
    display_logic = complete_stats['rankings'].get('display_logic', {})
    region_rows = ""
    valid_region_count = 0
    
    if complete_stats['attendance_analysis']['region_breakdown']:
        for region in complete_stats['attendance_analysis']['region_breakdown']:
            region_name = region.get('region_name', '未知区域')
            # 跳过完全无效的区域，但保留有意义的数据
            if region_name in ['', None] or (region_name in ['未知区域', '未知'] and region.get('工作天数', 0) == 0):
                continue
                
            valid_region_count += 1
            region_rate = region.get('大区出勤率', 0)
            region_rows += f"""
            <tr>
                <td>{region_name}</td>
                <td>{region.get('工作天数', 0)}天</td>
                <td>{region.get('所有天数', 0)}天</td>
                <td class="{'highlight-good' if region_rate > 0.8 else 'highlight-bad'}">{region_rate:.1%}</td>
            </tr>
            """
    
    # 确保区域表格总是显示（即使只有一个区域或默认区域）
    if region_rows or complete_stats['attendance_analysis']['region_breakdown']:
        effective_regions = display_logic.get('effective_regions', valid_region_count)
        if effective_regions > 1:
            title = f"🌍 各区域出勤率详情 ({effective_regions}个区域)"
        elif valid_region_count == 1:
            title = "🌍 区域出勤率详情"
        else:
            title = "🌍 区域出勤率概况"
        
        # 如果没有有效的区域行，生成一个汇总行
        if not region_rows:
            total_expected = complete_stats['attendance_analysis']['total_expected_days']
            total_actual = complete_stats['attendance_analysis']['total_actual_days']
            overall_rate = complete_stats['attendance_analysis']['overall_rate']
            primary_region = display_logic.get('primary_region', '主要区域')
            
            region_rows = f"""
            <tr>
                <td>{primary_region}</td>
                <td>{total_actual}天</td>
                <td>{total_expected}天</td>
                <td class="{'highlight-good' if overall_rate > 0.8 else 'highlight-bad'}">{overall_rate:.1%}</td>
            </tr>
            """
        
        tables['region_breakdown'] = f"""
        <div class="region-breakdown-section">
            <h3>{title}</h3>
            <table class="data-table">
                <thead>
                    <tr><th>区域名称</th><th>实际出勤天数</th><th>应出勤天数</th><th>出勤率</th></tr>
                </thead>
                <tbody>
                    {region_rows}
                </tbody>
            </table>
        </div>
        """
    
    # 4. 设备排名表（确保总是显示，添加项目信息）
    top_device_rows = ""
    if complete_stats['rankings'].get('top_devices'):
        for i, device in enumerate(complete_stats['rankings']['top_devices'], 1):
            work_time = device.get('总工作时间', 0)
            project_name = device.get('project_name', '未知项目')
            region_name = device.get('region_name', '未知区域')
            
            # 处理区域和项目显示逻辑
            if display_logic.get('effective_regions', 0) <= 1:
                # 单区域情况，重点显示项目
                location_info = f"{project_name}"
            else:
                # 多区域情况，显示项目和区域
                location_info = f"{project_name}<br><small>({region_name})</small>"
            
            top_device_rows += f"""
            <tr>
                <td>{i}</td>
                <td>{device.get('imei', '未知')[-6:]}</td>
                <td>{device.get('type', '未知')}</td>
                <td>{location_info}</td>
                <td class="highlight-good">{work_time:.1f}小时</td>
            </tr>
            """
    else:
        # 如果没有排名数据，显示说明信息
        top_device_rows = """
        <tr>
            <td colspan="5" style="text-align: center; color: #666;">暂无足够数据进行设备排名</td>
        </tr>
        """
    
    # 根据区域数量调整表头
    location_header = "所属项目" if display_logic.get('effective_regions', 0) <= 1 else "所属项目/区域"
    
    # 确保设备排名表总是显示
    tables['top_devices'] = f"""
    <div class="top-devices-section">
        <h3>🏆 工作时间排名前三设备</h3>
        <table class="data-table">
            <thead>
                <tr><th>排名</th><th>设备编号</th><th>设备类型</th><th>{location_header}</th><th>总工作时间</th></tr>
            </thead>
            <tbody>
                {top_device_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 5. 低效设备表（确保总是显示，添加项目信息）
    bottom_device_rows = ""
    if complete_stats['rankings'].get('bottom_devices'):
        for i, device in enumerate(complete_stats['rankings']['bottom_devices'], 1):
            work_time = device.get('总工作时间', 0)
            project_name = device.get('project_name', '未知项目')
            region_name = device.get('region_name', '未知区域')
            
            # 处理区域和项目显示逻辑
            if display_logic.get('effective_regions', 0) <= 1:
                # 单区域情况，重点显示项目
                location_info = f"{project_name}"
            else:
                # 多区域情况，显示项目和区域
                location_info = f"{project_name}<br><small>({region_name})</small>"
            
            bottom_device_rows += f"""
            <tr>
                <td>倒数第{i}</td>
                <td>{device.get('imei', '未知')[-6:]}</td>
                <td>{device.get('type', '未知')}</td>
                <td>{location_info}</td>
                <td class="highlight-bad">{work_time:.1f}小时</td>
            </tr>
            """
    else:
        # 如果没有底部排名数据，显示说明信息
        bottom_device_rows = """
        <tr>
            <td colspan="5" style="text-align: center; color: #666;">所有设备表现均衡，无需关注低效设备</td>
        </tr>
        """
    
    # 根据区域数量调整表头
    location_header = "所属项目" if display_logic.get('effective_regions', 0) <= 1 else "所属项目/区域"
    
    # 确保低效设备表总是显示
    tables['bottom_devices'] = f"""
    <div class="bottom-devices-section">
        <h3>⚠️ 工作时间排名后三设备</h3>
        <table class="data-table">
            <thead>
                <tr><th>排名</th><th>设备编号</th><th>设备类型</th><th>{location_header}</th><th>总工作时间</th></tr>
            </thead>
            <tbody>
                {bottom_device_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 6. 异常设备表
    idle_count = complete_stats['anomaly_detection']['idle_count']
    low_efficiency_count = len(complete_stats['anomaly_detection']['low_efficiency_devices'])
    
    anomaly_info = f"""
    <div class="anomaly-section">
        <h3>🔍 异常设备统计</h3>
        <table class="data-table">
            <tr><td>完全闲置设备</td><td class="{'highlight-bad' if idle_count > 0 else 'highlight-good'}">{idle_count}台</td></tr>
            <tr><td>低效设备</td><td class="{'highlight-bad' if low_efficiency_count > 0 else 'highlight-good'}">{low_efficiency_count}台</td></tr>
            <tr><td>正常工作设备</td><td class="highlight-good">{complete_stats['basic_info']['total_devices'] - idle_count - low_efficiency_count}台</td></tr>
        </table>
    </div>
    """
    
    if complete_stats['anomaly_detection']['low_efficiency_devices']:
        low_efficiency_rows = ""
        for device in complete_stats['anomaly_detection']['low_efficiency_devices']:
            work_time = device.get('总工作时间', 0)
            project_name = device.get('project_name', '未知项目')
            region_name = device.get('region_name', '未知区域')
            
            # 处理区域和项目显示逻辑
            if display_logic.get('effective_regions', 0) <= 1:
                # 单区域情况，重点显示项目
                location_info = f"{project_name}"
            else:
                # 多区域情况，显示项目和区域
                location_info = f"{project_name}<br><small>({region_name})</small>"
            
            low_efficiency_rows += f"""
            <tr>
                <td>{device.get('imei', '未知')[-6:]}</td>
                <td>{device.get('type', '未知')}</td>
                <td>{location_info}</td>
                <td class="highlight-bad">{work_time:.1f}小时</td>
            </tr>
            """
        
        # 根据区域数量调整表头
        location_header = "所属项目" if display_logic.get('effective_regions', 0) <= 1 else "所属项目/区域"
        
        anomaly_info += f"""
        <div class="low-efficiency-details">
            <h4>低效设备详情</h4>
            <table class="data-table">
                <thead>
                    <tr><th>设备编号</th><th>设备类型</th><th>{location_header}</th><th>总工作时间</th></tr>
                </thead>
                <tbody>
                    {low_efficiency_rows}
                </tbody>
            </table>
        </div>
        """
    
    tables['anomaly_detection'] = anomaly_info
    
    # 7. 项目排名表（智能显示逻辑）
    if (complete_stats['rankings'].get('top_projects') and 
        display_logic.get('should_show_project_rankings', False)):
        
        project_rows = ""
        for i, project in enumerate(complete_stats['rankings']['top_projects'], 1):
            work_time = project.get('总工作时间', 0)
            device_count = project.get('设备数量', 0)
            avg_work_time = project.get('平均工作时间', 0)
            regions_count = project.get('涉及区域数', 1)
            
            # 计算项目效率指标
            efficiency_indicator = ""
            if device_count > 0:
                per_device_time = work_time / device_count
                if per_device_time > 8:  # 假设8小时为优秀标准
                    efficiency_indicator = "💚"
                elif per_device_time > 4:
                    efficiency_indicator = "💛"
                else:
                    efficiency_indicator = "💔"
            
            project_rows += f"""
            <tr>
                <td>{i}</td>
                <td>{project.get('project_name', '未知项目')} {efficiency_indicator}</td>
                <td>{device_count}台</td>
                <td class="highlight-good">{work_time:.1f}小时</td>
                <td>{avg_work_time:.1f}小时</td>
                <td>{project.get('工作天数', 0)}天</td>
            </tr>
            """
        
        # 分析项目分布情况
        project_analysis = complete_stats['rankings'].get('project_distribution_analysis', {})
        cross_region_count = project_analysis.get('cross_region_count', 0)
        total_projects = project_analysis.get('total_projects', 0)
        
        # 根据项目分布调整标题
        if cross_region_count > 0:
            title = f"📈 项目表现排名 ({total_projects}个项目，{cross_region_count}个跨区域)"
        else:
            title = f"📈 项目表现排名 ({total_projects}个项目)"
        
        tables['project_rankings'] = f"""
        <div class="project-rankings-section">
            <h3>{title}</h3>
            <table class="data-table">
                <thead>
                    <tr><th>排名</th><th>项目名称</th><th>设备数量</th><th>总工作时间</th><th>平均工作时间</th><th>工作天数</th></tr>
                </thead>
                <tbody>
                    {project_rows}
                </tbody>
            </table>
            <div style="margin-top: 10px; font-size: 12px; color: #666;">
                💚 高效项目 | 💛 正常项目 | 💔 需关注项目
            </div>
        </div>
        """
    
    # 8. 效率分布表
    efficiency_dist = complete_stats['performance_analysis']['efficiency_distribution']
    tables['efficiency_distribution'] = f"""
    <div class="efficiency-distribution-section">
        <h3>📊 设备效率分布</h3>
        <table class="data-table">
            <tr><td>高效设备</td><td class="highlight-good">{efficiency_dist['high_efficiency']}台</td></tr>
            <tr><td>正常效率设备</td><td>{efficiency_dist['normal_efficiency']}台</td></tr>
            <tr><td>低效设备</td><td class="highlight-bad">{efficiency_dist['low_efficiency']}台</td></tr>
        </table>
    </div>
    """
    
    # 9. 综合统计表（显示均值和关键指标）
    utilization_rate = complete_stats['performance_analysis']['utilization_rate']
    avg_work_time = complete_stats['device_details']['average_work_time']
    total_devices = complete_stats['basic_info']['total_devices']
    effective_regions = display_logic.get('effective_regions', 0)
    effective_projects = display_logic.get('effective_projects', 0)
    
    # 计算更多有意义的统计指标
    working_devices = total_devices - complete_stats['anomaly_detection']['idle_count']
    efficiency_rate = working_devices / total_devices if total_devices > 0 else 0
    
    tables['summary_stats'] = f"""
    <div class="summary-stats-section">
        <h3>📈 综合统计分析</h3>
        <table class="data-table">
            <tr><td>设备利用率</td><td class="{'highlight-good' if utilization_rate > 0.8 else 'highlight-bad'}">{utilization_rate:.1%}</td></tr>
            <tr><td>设备工作率</td><td class="{'highlight-good' if efficiency_rate > 0.9 else 'highlight-bad'}">{efficiency_rate:.1%} ({working_devices}/{total_devices})</td></tr>
            <tr><td>平均工作时长</td><td class="{'highlight-good' if avg_work_time > 6 else 'highlight-bad'}">{avg_work_time:.1f}小时/台</td></tr>
            <tr><td>覆盖范围</td><td>{effective_regions}个区域 | {effective_projects}个项目</td></tr>
            <tr><td>报告类型</td><td>{display_logic.get('report_focus_recommendation', '综合分析')}</td></tr>
            <tr><td>生成时间</td><td>{complete_stats['report_info']['generation_time']}</td></tr>
        </table>
    </div>
    """
    
    return tables


def generate_health_report_tables(complete_stats):
    """
    生成健康报告HTML表格内容，为AI分析提供结构化数据
    
    Args:
        complete_stats: 完整的健康统计数据
    
    Returns:
        dict: 包含各类HTML表格的字典
    """
    tables = {}
    
    # 1. 基础信息表
    basic_info = complete_stats['basic_info']
    tables['basic_info'] = f"""
    <div class="basic-info-section">
        <h3>📋 基础信息</h3>
        <table class="info-table">
            <tr><td>机构名称</td><td>{basic_info['member_name']}</td></tr>
            <tr><td>统计周期</td><td>{basic_info['period_start']} 至 {basic_info['period_end']}</td></tr>
            <tr><td>统计天数</td><td>{basic_info['period_days']}天</td></tr>
            <tr><td>员工总数</td><td>{basic_info['total_employees']}人</td></tr>
            <tr><td>异常员工数</td><td class="{'highlight-bad' if basic_info['exception_employees'] > 0 else 'highlight-good'}">{basic_info['exception_employees']}人</td></tr>
            <tr><td>健康员工数</td><td class="highlight-good">{basic_info['normal_employees']}人</td></tr>
            <tr><td>异常率</td><td class="{'highlight-bad' if basic_info['exception_rate'] > 0.1 else 'highlight-good'}">{basic_info['exception_rate']:.1%}</td></tr>
        </table>
    </div>
    """
    
    # 2. 健康状况总览
    health_assessment = complete_stats['health_assessment']
    tables['health_overview'] = f"""
    <div class="health-overview-section">
        <h3>🩺 健康状况总览</h3>
        <table class="data-table">
            <tr><td>整体健康评分</td><td class="{'highlight-good' if health_assessment['overall_health_score'] >= 80 else 'highlight-bad'}">{health_assessment['overall_health_score']}分</td></tr>
            <tr><td>健康状况等级</td><td class="{'highlight-good' if health_assessment['health_status'] == '良好' else 'highlight-warning'}">{health_assessment['health_status']}</td></tr>
            <tr><td>异常记录总数</td><td>{basic_info['total_exceptions']}条</td></tr>
            <tr><td>趋势分析</td><td>{health_assessment['trend_analysis']}</td></tr>
        </table>
    </div>
    """
    
    # 3. 异常等级分布统计表
    level_analysis = complete_stats['exception_level_analysis']
    level_rows = ""
    
    if level_analysis['level_distribution']:
        for level in level_analysis['level_distribution']:
            level_name = f"{level['异常等级']}级"
            level_desc = {1: "轻度异常", 2: "中度异常", 3: "重度异常", 4: "极重度异常"}.get(level['异常等级'], "未知")
            color_class = "highlight-good" if level['异常等级'] == 1 else ("highlight-warning" if level['异常等级'] == 2 else "highlight-bad")
            
            level_rows += f"""
            <tr>
                <td>{level_name}（{level_desc}）</td>
                <td class="{color_class}">{level['总异常次数']}次</td>
                <td class="{color_class}">{level['涉及人数']}人</td>
            </tr>
            """
    
    if not level_rows:  # 无异常数据时显示
        level_rows = """
        <tr>
            <td colspan="3" class="highlight-good">统计期间内无健康异常记录</td>
        </tr>
        """
    
    tables['exception_level_stats'] = f"""
    <div class="exception-level-section">
        <h3>📊 异常等级分布统计</h3>
        <table class="data-table">
            <thead>
                <tr><th>异常等级</th><th>异常次数</th><th>涉及人数</th></tr>
            </thead>
            <tbody>
                {level_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 4. 数据类型异常统计表
    datatype_analysis = complete_stats['datatype_analysis']
    datatype_rows = ""
    
    if datatype_analysis['type_breakdown']:
        for datatype in datatype_analysis['type_breakdown']:
            severity_class = "highlight-bad" if datatype['异常次数'] > 10 else ("highlight-warning" if datatype['异常次数'] > 5 else "highlight-good")
            datatype_rows += f"""
            <tr>
                <td>{datatype['数据类型']}</td>
                <td class="{severity_class}">{datatype['异常次数']}次</td>
                <td>{datatype['异常人数']}人</td>
                <td>{datatype['平均异常等级']:.1f}级</td>
                <td class="{'highlight-bad' if datatype['最高异常等级'] >= 3 else 'highlight-warning'}">{datatype['最高异常等级']}级</td>
            </tr>
            """
    
    if not datatype_rows:
        datatype_rows = """
        <tr>
            <td colspan="5" class="highlight-good">无数据类型异常记录</td>
        </tr>
        """
    
    tables['datatype_stats'] = f"""
    <div class="datatype-stats-section">
        <h3>🔍 数据类型异常统计</h3>
        <table class="data-table">
            <thead>
                <tr><th>数据类型</th><th>异常次数</th><th>异常人数</th><th>平均异常等级</th><th>最高异常等级</th></tr>
            </thead>
            <tbody>
                {datatype_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 5. 高风险员工排名表（前10名）
    rankings = complete_stats['rankings']
    high_risk_rows = ""
    
    if rankings.get('high_risk_employees'):
        for i, employee in enumerate(rankings['high_risk_employees'][:10], 1):
            risk_class = "highlight-bad" if employee['风险等级'] == '高风险' else "highlight-warning"
            high_risk_rows += f"""
            <tr>
                <td>{i}</td>
                <td>{employee['姓名']}</td>
                <td>{employee['项目名称']}</td>
                <td class="{risk_class}">{employee['异常总次数']}次</td>
                <td class="{'highlight-bad' if employee['最高异常等级'] >= 3 else 'highlight-warning'}">{employee['最高异常等级']}级</td>
                <td class="{risk_class}">{employee['风险等级']}</td>
            </tr>
            """
    
    if not high_risk_rows:
        high_risk_rows = """
        <tr>
            <td colspan="6" class="highlight-good">恭喜！暂无高风险员工</td>
        </tr>
        """
    
    tables['high_risk_employees'] = f"""
    <div class="high-risk-section">
        <h3>⚠️ 高风险员工排名（前10名）</h3>
        <table class="data-table">
            <thead>
                <tr><th>排名</th><th>姓名</th><th>项目名称</th><th>异常次数</th><th>最高异常等级</th><th>风险等级</th></tr>
            </thead>
            <tbody>
                {high_risk_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 6. 项目异常统计对比表
    project_analysis = complete_stats['project_analysis']
    project_rows = ""
    
    if project_analysis['project_breakdown']:
        for project in project_analysis['project_breakdown']:
            exception_rate = project.get('异常率', 0)
            rate_class = "highlight-good" if exception_rate < 0.1 else ("highlight-warning" if exception_rate < 0.3 else "highlight-bad")
            
            project_rows += f"""
            <tr>
                <td>{project['项目名称']}</td>
                <td>{project['异常人数']}人</td>
                <td>{project['异常总次数']}次</td>
                <td class="{rate_class}">{exception_rate:.1%}</td>
                <td>{project['平均异常等级']:.1f}级</td>
                <td class="{'highlight-bad' if project['最高异常等级'] >= 3 else 'highlight-warning'}">{project['最高异常等级']}级</td>
            </tr>
            """
    
    if not project_rows:
        project_rows = """
        <tr>
            <td colspan="6">暂无项目异常统计数据</td>
        </tr>
        """
    
    tables['project_comparison'] = f"""
    <div class="project-comparison-section">
        <h3>🏢 项目异常统计对比</h3>
        <table class="data-table">
            <thead>
                <tr><th>项目名称</th><th>异常人数</th><th>异常次数</th><th>异常率</th><th>平均异常等级</th><th>最高异常等级</th></tr>
            </thead>
            <tbody>
                {project_rows}
            </tbody>
        </table>
    </div>
    """
    
    # 7. 员工风险分布统计表
    employee_details = complete_stats['employee_details']
    risk_distribution = employee_details.get('risk_distribution', {})
    
    tables['risk_distribution'] = f"""
    <div class="risk-distribution-section">
        <h3>📈 员工风险分布统计</h3>
        <table class="data-table">
            <tr><td>高风险员工</td><td class="highlight-bad">{risk_distribution.get('高风险', 0)}人</td></tr>
            <tr><td>中风险员工</td><td class="highlight-warning">{risk_distribution.get('中风险', 0)}人</td></tr>
            <tr><td>低风险员工</td><td class="highlight-good">{risk_distribution.get('低风险', 0)}人</td></tr>
            <tr><td>人均异常次数</td><td>{employee_details.get('average_exceptions_per_employee', 0):.1f}次</td></tr>
        </table>
    </div>
    """
    
    # 8. 紧急关注员工表（如果有的话）
    urgent_employees = complete_stats['anomaly_detection'].get('urgent_attention_needed', [])
    urgent_rows = ""
    
    if urgent_employees:
        for employee in urgent_employees[:5]:  # 只显示前5名
            urgent_rows += f"""
            <tr>
                <td class="highlight-bad">{employee['姓名']}</td>
                <td>{employee['项目名称']}</td>
                <td class="highlight-bad">{employee['异常总次数']}次</td>
                <td class="highlight-bad">{employee['最高异常等级']}级</td>
            </tr>
            """
        
        tables['urgent_attention'] = f"""
        <div class="urgent-attention-section">
            <h3>🚨 需要紧急关注的员工</h3>
            <table class="data-table">
                <thead>
                    <tr><th>姓名</th><th>项目名称</th><th>异常次数</th><th>最高异常等级</th></tr>
                </thead>
                <tbody>
                    {urgent_rows}
                </tbody>
            </table>
        </div>
        """
    
    # 9. 时间分析统计表（新增）
    time_analysis = complete_stats.get('time_analysis', {})
    peak_analysis = time_analysis.get('peak_analysis', {})
    temporal_insights = time_analysis.get('temporal_insights', {})
    
    # 异常时间分布表
    time_tables = ""
    
    # 9.1 异常高峰时段分析
    if peak_analysis:
        peak_hours = peak_analysis.get('peak_hours', [])
        peak_days = peak_analysis.get('peak_days', [])
        hour_concentration = peak_analysis.get('hour_concentration_rate', 0)
        day_concentration = peak_analysis.get('day_concentration_rate', 0)
        time_patterns = peak_analysis.get('time_patterns', [])
        
        peak_hours_str = '、'.join([f"{h}:00" for h in peak_hours[:3]]) if peak_hours else "无明显高峰"
        peak_days_str = '、'.join(peak_days[:2]) if peak_days else "无明显差异"
        patterns_str = '；'.join(time_patterns) if time_patterns else "无明显规律"
        
        time_tables += f"""
        <div class="time-peak-section">
            <h3>⏰ 异常时间分布分析</h3>
            <table class="data-table">
                <tr><td>异常高峰时段</td><td class="highlight-warning">{peak_hours_str}</td></tr>
                <tr><td>异常高峰日期</td><td class="highlight-warning">{peak_days_str}</td></tr>
                <tr><td>时段集中度</td><td class="{'highlight-bad' if hour_concentration > 50 else 'highlight-warning' if hour_concentration > 30 else 'highlight-good'}">{hour_concentration}%</td></tr>
                <tr><td>日期集中度</td><td class="{'highlight-bad' if day_concentration > 60 else 'highlight-warning' if day_concentration > 40 else 'highlight-good'}">{day_concentration}%</td></tr>
                <tr><td>时间规律特征</td><td>{patterns_str}</td></tr>
            </table>
        </div>
        """
        
        # 9.2 时间洞察分析
        most_problematic_hour = temporal_insights.get('most_problematic_hour')
        most_problematic_day = temporal_insights.get('most_problematic_day')
        daily_avg = temporal_insights.get('daily_average_exceptions', 0)
        peak_ratio = temporal_insights.get('peak_to_average_ratio', 0)
        
        time_tables += f"""
        <div class="time-insights-section">
            <h3>🔍 时间规律洞察</h3>
            <table class="data-table">
                <tr><td>最高风险时段</td><td class="highlight-bad">{most_problematic_hour}:00</td></tr>
                <tr><td>最高风险日期</td><td class="highlight-bad">{most_problematic_day}</td></tr>
                <tr><td>日均异常次数</td><td>{daily_avg:.1f}次</td></tr>
                <tr><td>高峰倍数</td><td class="{'highlight-bad' if peak_ratio > 3 else 'highlight-warning' if peak_ratio > 2 else 'highlight-good'}">{peak_ratio:.1f}倍</td></tr>
            </table>
        </div>
        """
    
    tables['time_analysis'] = time_tables if time_tables else """
    <div class="time-analysis-section">
        <h3>⏰ 时间分析</h3>
        <table class="data-table">
            <tr><td colspan="2" class="highlight-good">统计期间数据不足，无法进行时间分析</td></tr>
        </table>
    </div>
    """
    
    # 10. 异常趋势摘要表
    severity_summary = level_analysis['severity_summary']
    tables['severity_summary'] = f"""
    <div class="severity-summary-section">
        <h3>📋 异常严重程度摘要</h3>
        <table class="data-table">
            <tr><td>轻度异常</td><td class="highlight-good">{severity_summary['轻度异常']}次</td></tr>
            <tr><td>中度异常</td><td class="highlight-warning">{severity_summary['中度异常']}次</td></tr>
            <tr><td>重度异常</td><td class="highlight-bad">{severity_summary['重度异常']}次</td></tr>
            <tr><td>总计</td><td>{sum(severity_summary.values())}次</td></tr>
        </table>
    </div>
    """
    
    print(f"📊 健康报告表格生成完成，共生成{len(tables)}个表格")
    return tables


async def generate_health_ai_analysis_from_tables(report_tables, complete_stats, member_name, start_time, end_time):
    """
    基于健康报告表格内容创建AI分析提示（专用于健康报告）
    
    Args:
        report_tables: 生成的HTML表格
        complete_stats: 完整健康统计数据
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: AI分析内容
    """
    try:
        print(f"🤖 开始生成健康AI分析内容，机构: {member_name}")
        
        # 安全提取关键健康数据点
        try:
            basic_info = complete_stats.get('basic_info', {})
            exception_rate = basic_info.get('exception_rate', 0)
            total_employees = basic_info.get('total_employees', 0)
            exception_employees = basic_info.get('exception_employees', 0)
            health_score = complete_stats.get('health_assessment', {}).get('overall_health_score', 0)
            health_status = complete_stats.get('health_assessment', {}).get('health_status', '未知')
            
            # 异常检测数据
            anomaly_detection = complete_stats.get('anomaly_detection', {})
            high_risk_employees = anomaly_detection.get('high_risk_employees', 0)
            urgent_attention_needed = len(anomaly_detection.get('urgent_attention_needed', []))
            
            # 项目分析数据
            project_analysis = complete_stats.get('project_analysis', {})
            project_count = project_analysis.get('project_count', 0)
            
            # 时间分析数据
            time_analysis = complete_stats.get('time_analysis', {})
            peak_analysis = time_analysis.get('peak_analysis', {})
            temporal_insights = time_analysis.get('temporal_insights', {})
            peak_hours = peak_analysis.get('peak_hours', [])
            peak_days = peak_analysis.get('peak_days', [])
            most_problematic_hour = temporal_insights.get('most_problematic_hour')
            most_problematic_day = temporal_insights.get('most_problematic_day')
            hour_concentration = peak_analysis.get('hour_concentration_rate', 0)
            time_patterns = peak_analysis.get('time_patterns', [])
            
        except Exception as e:
            print(f"⚠️ 提取健康数据指标时出错: {e}")
            # 设置默认值
            exception_rate = 0.0
            total_employees = 0
            exception_employees = 0
            health_score = 0.0
            health_status = '未知'
            high_risk_employees = 0
            urgent_attention_needed = 0
            project_count = 0
            peak_hours = []
            peak_days = []
            most_problematic_hour = None
            most_problematic_day = None
            hour_concentration = 0
            time_patterns = []
        
        # 验证表格数据完整性
        table_count = len([k for k, v in report_tables.items() if v and v.strip()])
        print(f"📊 已生成健康表格数量: {table_count}")
        
        if table_count == 0:
            print("⚠️ 警告：没有生成任何健康表格数据")
            return "由于数据处理异常，无法生成详细的健康分析内容。请检查数据源完整性。"
        
        # 构建基于健康表格的AI提示
        peak_hours_str = '、'.join([f"{h}:00" for h in peak_hours[:3]]) if peak_hours else "无明显高峰"
        peak_days_str = '、'.join(peak_days[:2]) if peak_days else "无明显差异"
        patterns_str = '；'.join(time_patterns) if time_patterns else "无明显规律"
        
        prompt = f"""
基于以下{member_name}的员工健康监测数据表格，请生成专业的健康分析报告内容。

## 健康数据表格内容：

{report_tables.get('basic_info', '')}

{report_tables.get('health_overview', '')}

{report_tables.get('exception_level_stats', '')}

{report_tables.get('datatype_stats', '')}

{report_tables.get('high_risk_employees', '')}

{report_tables.get('project_comparison', '')}

{report_tables.get('risk_distribution', '')}

{report_tables.get('time_analysis', '')}

{report_tables.get('urgent_attention', '')}

{report_tables.get('severity_summary', '')}

## 关键健康指标：
- 员工总数：{total_employees}人
- 异常员工数：{exception_employees}人
- 异常率：{exception_rate:.1%}
- 整体健康评分：{health_score}分
- 健康状况等级：{health_status}
- 高风险员工：{high_risk_employees}人
- 需紧急关注：{urgent_attention_needed}人
- 涉及项目：{project_count}个

## 时间规律分析：
- 异常高峰时段：{peak_hours_str}
- 异常高峰日期：{peak_days_str}
- 最高风险时段：{most_problematic_hour if most_problematic_hour else '无'}:00
- 最高风险日期：{most_problematic_day if most_problematic_day else '无'}
- 时段集中度：{hour_concentration}%
- 时间规律特征：{patterns_str}

## 分析要求：
请基于以上健康表格数据，生成以下结构的分析内容，每个部分用明确的标题分隔：

**第一部分 - 健康状况总结**
用2-3个完整段落概述统计期间的整体健康状况，包括异常率、健康评分等核心指标的综合分析。

**第二部分 - 关键发现与时间规律**
用段落形式阐述3-5个最重要的健康发现或异常趋势，每个发现用一个段落详细说明。特别关注时间分析中发现的异常高峰时段、集中度和规律特征，分析这些时间模式背后的可能原因。

**第三部分 - 风险识别与时间关联**
以段落形式深入分析当前存在的健康风险，包括高风险员工、异常类型分布等。重点结合时间分析数据，分析风险在时间维度上的分布特征，如特定时段或日期的风险集中情况。

**第四部分 - 积极表现**
用段落形式总结健康状况良好的方面，如健康员工比例、表现良好的项目等。

**第五部分 - 时间导向的健康管理建议**
以连续段落形式提供具体的健康管理建议，特别针对时间分析中发现的高峰时段和集中模式，制定有针对性的管理措施。建议包括但不限于：针对特定时段的预防措施、工作安排优化、健康监测重点时间等。

**第六部分 - 后续重点工作与时间管理**
用段落形式建议下一阶段需要重点关注的健康监测事项和改进方向。特别强调基于时间规律的管理策略，如在高风险时段加强监测、调整作息安排等具体措施。

## 输出要求：
1. 只输出文字分析内容，不要重复表格数据
2. 每个部分写成完整的段落，段落间有逻辑连接
3. 内容专业客观，基于健康数据事实
4. 语言流畅，适合管理层阅读
5. 篇幅控制在800-1200字
6. 不要使用"AI"、"根据数据"等表述，直接给出分析结论
7. 重点关注员工健康风险和管理建议
8. 体现对员工健康关怀的人性化管理理念
9. 特别强调时间维度的分析，将时间规律作为重要的管理依据
10. 基于时间集中度和高峰分析，提供精确可行的改进建议
"""
        
        # 调用AI接口
        print("🔄 调用AI接口生成健康分析...")
        ai_content = await invoke_openai_only_result(prompt)
        
        if not ai_content or ai_content.strip() == "":
            print("⚠️ AI返回空内容，使用默认分析")
            ai_content = generate_default_health_analysis(complete_stats, member_name)
        
        print(f"✅ 健康AI分析生成完成，内容长度: {len(ai_content)} 字符")
        return ai_content.strip()
        
    except Exception as e:
        print(f"❌ 生成健康AI分析失败: {str(e)}")
        import traceback
        traceback.print_exc()
        
        # 返回默认分析内容
        return generate_default_health_analysis(complete_stats, member_name)


def generate_default_health_analysis(complete_stats, member_name):
    """生成默认的健康分析内容（当AI调用失败时使用）"""
    basic_info = complete_stats.get('basic_info', {})
    exception_rate = basic_info.get('exception_rate', 0)
    health_score = complete_stats.get('health_assessment', {}).get('overall_health_score', 0)
    
    if exception_rate == 0:
        return f"""
**第一部分 - 健康状况总结**

{member_name}在本统计周期内展现出了良好的整体健康状况。全体员工的健康指标均保持在正常范围内，未发现异常情况，健康评分达到{health_score}分，表明组织的健康管理工作取得了显著成效。

**第二部分 - 积极表现**

所有员工的各项健康指标都保持稳定，包括血氧、血压、体温、心率等关键生理指标均未出现异常波动。这充分体现了员工良好的身体素质和组织有效的健康管理措施。

**第三部分 - 健康管理建议**

建议继续保持现有的健康管理水平，定期开展健康宣教活动，鼓励员工养成良好的生活习惯。同时建立预防性健康监测机制，确保健康状况的持续稳定。

**第四部分 - 后续重点工作**

未来应重点关注预防性健康管理，建立更完善的健康档案系统，定期组织健康体检，为员工提供更全面的健康保障服务。
        """
    else:
        return f"""
**第一部分 - 健康状况总结**

{member_name}在本统计周期内的健康监测显示，异常率为{exception_rate:.1%}，整体健康评分{health_score}分。虽然大部分员工健康状况良好，但仍需关注异常情况的分析和改进。

**第二部分 - 风险识别**

发现部分员工存在健康异常情况，需要进一步分析异常原因，制定针对性的健康干预措施。

**第三部分 - 健康管理建议**

建议加强对异常员工的健康跟踪，及时提供医疗咨询和健康指导，同时完善健康监测体系，提高异常情况的早期发现和处理能力。

**第四部分 - 后续重点工作**

重点关注高风险员工的健康状况变化，建立健康预警机制，定期评估健康管理措施的有效性。
        """


async def generate_ai_analysis_from_tables(report_tables, complete_stats, member_name, start_time, end_time):
    """
    基于生成的表格内容创建AI分析提示（增强容错处理）
    
    Args:
        report_tables: 生成的HTML表格
        complete_stats: 完整统计数据
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: AI分析内容
    """
    try:
        print(f"🤖 开始生成AI分析内容，机构: {member_name}")
        
        # 安全提取关键数据点
        try:
            attendance_rate = complete_stats.get('attendance_analysis', {}).get('overall_rate', 0)
            idle_count = complete_stats.get('anomaly_detection', {}).get('idle_count', 0)
            low_efficiency_devices = complete_stats.get('anomaly_detection', {}).get('low_efficiency_devices', [])
            low_efficiency_count = len(low_efficiency_devices) if low_efficiency_devices else 0
            total_devices = complete_stats.get('basic_info', {}).get('total_devices', 0)
            utilization_rate = complete_stats.get('performance_analysis', {}).get('utilization_rate', 0)
        except Exception as e:
            print(f"⚠️ 提取数据指标时出错: {e}")
            # 设置默认值
            attendance_rate = 0.0
            idle_count = 0
            low_efficiency_count = 0
            total_devices = 0
            utilization_rate = 0.0
        
        # 验证表格数据完整性
        table_count = len([k for k, v in report_tables.items() if v and v.strip()])
        print(f"📊 已生成表格数量: {table_count}")
        
        if table_count == 0:
            print("⚠️ 警告：没有生成任何表格数据")
            return "由于数据处理异常，无法生成详细的分析内容。请检查数据源完整性。"
        
        # 构建基于表格的AI提示
        prompt = f"""
基于以下{member_name}的设备工作数据表格，请生成专业的分析报告内容。

## 数据表格内容：

{report_tables.get('basic_info', '')}

{report_tables.get('attendance_analysis', '')}

{report_tables.get('region_breakdown', '')}

{report_tables.get('top_devices', '')}

{report_tables.get('bottom_devices', '')}

{report_tables.get('anomaly_detection', '')}

{report_tables.get('efficiency_distribution', '')}

{report_tables.get('summary_stats', '')}

## 关键数据指标：
- 整体出勤率：{attendance_rate:.1%}
- 设备利用率：{utilization_rate:.1%}
- 完全闲置设备：{idle_count}台
- 低效设备：{low_efficiency_count}台
- 设备总数：{total_devices}台

## 分析要求：
请基于以上表格数据，生成以下结构的分析内容，每个部分用明确的标题分隔：

**第一部分 - 数据概况总结**
用2-3个完整段落概述统计期间的整体运营情况，包括出勤率、设备利用率等核心指标的综合分析。

**第二部分 - 关键发现**
用段落形式阐述3-5个最重要的发现或趋势，每个发现用一个段落详细说明。

**第三部分 - 问题识别**
以段落形式深入分析当前存在的主要问题，包括闲置设备、低效设备等问题的影响和可能原因。

**第四部分 - 成效亮点**
用段落形式总结表现良好的方面，如高效设备、表现优异的区域等。

**第五部分 - 管理建议**
以连续段落形式提供具体的管理建议，针对发现的问题提出可操作的解决方案。

**第六部分 - 下期重点**
用段落形式建议下一阶段需要重点关注的事项和改进方向。

## 输出要求：
1. 只输出文字分析内容，不要重复表格数据
2. 每个部分写成完整的段落，段落间有逻辑连接
3. 内容专业客观，基于数据事实
4. 语言流畅，适合管理层阅读
5. 篇幅控制在800-1200字
6. 不要使用"AI"、"根据数据"等表述，直接给出分析结论
"""
        
        print(f"📝 提示词长度: {len(prompt)} 字符")
        
        # 调用AI生成分析内容，添加超时和重试机制
        try:
            # ai_content = await invoke_openai_only_result(prompt)
            ai_content = await invoke_laozhangapi_only_result(prompt,model="o3")

            if not ai_content or len(ai_content.strip()) < 100:
                raise ValueError("AI返回内容过短或为空")
            
            print(f"✅ AI分析内容生成成功，长度: {len(ai_content)} 字符")
            return ai_content
            
        except Exception as ai_error:
            print(f"❌ AI调用失败: {ai_error}")
            # 生成回退内容
            fallback_content = f"""
**第一部分 - 数据概况总结**

{member_name}在{start_time.strftime('%Y年%m月%d日')}至{end_time.strftime('%Y年%m月%d日')}期间，共管理{total_devices}台清洁设备，整体出勤率为{attendance_rate:.1%}。设备利用率达到{utilization_rate:.1%}，基本满足清洁作业需求。

**第二部分 - 关键发现**

通过数据分析发现，当前设备管理存在{idle_count}台完全闲置设备，{low_efficiency_count}台低效设备需要关注。这些设备的运行状况直接影响整体清洁效率。

**第三部分 - 问题识别**

主要问题集中在设备利用率不均和区域配置不平衡方面。部分设备长期处于低效状态，影响整体运营效率。

**第四部分 - 成效亮点**

大部分设备保持正常运行状态，核心清洁任务得到有效执行。高效设备表现稳定，为清洁服务提供了可靠保障。

**第五部分 - 管理建议**

建议加强设备维护管理，优化设备配置，提高闲置设备利用率。建立设备效率监控机制，及时发现并解决设备运行问题。

**第六部分 - 下期重点**

下阶段应重点关注设备利用率提升和区域配置优化，建立完善的设备管理体系，确保清洁服务质量持续改进。
"""
            print(f"🛡️ 使用回退内容，长度: {len(fallback_content)} 字符")
            return fallback_content
            
    except Exception as e:
        print(f"💥 生成AI分析内容时发生严重错误: {e}")
        # 最终回退内容
        return f"""
**智能分析内容**

{member_name}设备运营数据分析报告生成过程中遇到技术问题，系统正在自动修复。请联系技术支持团队获取详细的分析报告。

本次统计周期：{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}
报告生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

如需详细分析内容，请重新生成报告或联系技术支持。
"""


def render_final_report(complete_stats, report_tables, ai_content, member_name, start_time, end_time):
    """
    渲染最终报告HTML
    
    Args:
        complete_stats: 完整统计数据
        report_tables: HTML表格
        ai_content: AI生成的分析内容
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: 最终的HTML报告
    """
    # 解析AI内容为段落（增强版）
    ai_sections = {}
    current_section = None
    current_content = []
    
    print(f"🔍 开始解析AI内容，总长度: {len(ai_content)} 字符")
    
    lines = ai_content.split('\n')
    for i, line in enumerate(lines):
        line = line.strip()
        
        # 检测多种标题格式
        is_title = False
        title_text = None
        
        # 格式1：**标题**
        if line.startswith('**') and line.endswith('**') and len(line) > 4:
            is_title = True
            title_text = line.strip('*').strip()
        # 格式2：第一部分 - 标题
        elif line.startswith('第') and ('部分' in line or '部分 -' in line):
            is_title = True
            title_text = line
        # 格式3：## 标题
        elif line.startswith('##') and len(line) > 3:
            is_title = True
            title_text = line.strip('#').strip()
        # 格式4：单独的标题行（如果前后都是空行）
        elif (line and not line.startswith('**') and 
              ('总结' in line or '发现' in line or '问题' in line or '亮点' in line or '建议' in line or '重点' in line) and
              len(line) < 50):
            # 检查是否像标题（短，包含关键词）
            if i > 0 and i < len(lines) - 1:
                prev_line = lines[i-1].strip()
                next_line = lines[i+1].strip()
                if not prev_line and next_line:  # 前面是空行，后面有内容
                    is_title = True
                    title_text = line
        
        if is_title:
            # 保存前一节内容
            if current_section and current_content:
                content_text = '<br><br>'.join(current_content)
                ai_sections[current_section] = content_text
                print(f"✅ 保存章节: {current_section} ({len(content_text)} 字符)")
            
            # 开始新节
            current_section = title_text
            current_content = []
            print(f"🆕 开始新章节: {current_section}")
        elif line and current_section:
            current_content.append(line)
        elif line and not current_section:
            # 如果还没有章节标题，但有内容，创建一个默认章节
            if not current_section:
                current_section = "主要分析内容"
                current_content = []
                print(f"🆕 创建默认章节: {current_section}")
            current_content.append(line)
    
    # 保存最后一节
    if current_section and current_content:
        content_text = '<br><br>'.join(current_content)
        ai_sections[current_section] = content_text
        print(f"✅ 保存最后章节: {current_section} ({len(content_text)} 字符)")
    
    # 如果完全没有解析出内容，创建一个兜底章节
    if not ai_sections and ai_content.strip():
        ai_sections["智能分析"] = ai_content.replace('\n', '<br>')
        print(f"🛡️ 创建兜底章节，原始内容长度: {len(ai_content)}")
    
    print(f"📊 AI内容解析完成，共{len(ai_sections)}个章节: {list(ai_sections.keys())}")
    
    # 构建最终HTML
    html_content = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>{member_name} 设备工作分析报告</title>
        <style>
            body {{
                font-family: "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
                line-height: 1.6;
                margin: 40px;
                color: #333;
                background-color: #fff;
            }}
            .report-header {{
                text-align: center;
                margin-bottom: 40px;
                border-bottom: 2px solid #1f4e79;
                padding-bottom: 20px;
            }}
            .report-title {{
                font-size: 28px;
                color: #1f4e79;
                font-weight: bold;
                margin-bottom: 10px;
            }}
            .report-subtitle {{
                font-size: 18px;
                color: #666;
                margin-bottom: 20px;
            }}
            .data-table {{
                width: 100%;
                border-collapse: collapse;
                margin-bottom: 25px;
                font-size: 14px;
            }}
            .data-table th, .data-table td {{
                border: 1px solid #ddd;
                padding: 12px;
                text-align: center;
            }}
            .data-table th {{
                background-color: #1f4e79;
                color: white;
                font-weight: bold;
            }}
            .data-table tr:nth-child(even) {{
                background-color: #f9f9f9;
            }}
            .highlight-good {{
                color: #28a745;
                font-weight: bold;
            }}
            .highlight-bad {{
                color: #dc3545;
                font-weight: bold;
            }}
            .section {{
                margin: 30px 0;
                padding: 20px;
                border: 1px solid #e0e0e0;
                border-radius: 8px;
                background-color: #fafafa;
            }}
            .section h3 {{
                color: #1f4e79;
                margin-top: 0;
                margin-bottom: 15px;
                font-size: 20px;
            }}
            .section h4 {{
                color: #1f4e79;
                margin-bottom: 12px;
                border-bottom: 1px solid #e0e0e0;
                padding-bottom: 8px;
            }}
            .ai-analysis {{
                background-color: #f8f9fa;
                padding: 25px;
                border-left: 4px solid #1f4e79;
                margin: 30px 0;
            }}
            .ai-analysis h4 {{
                color: #1f4e79;
                margin-bottom: 15px;
            }}
            .ai-content {{
                text-align: justify;
                line-height: 1.8;
                margin-bottom: 20px;
            }}
            .info-table {{
                width: 100%;
                border-collapse: collapse;
            }}
            .info-table td {{
                border: 1px solid #ddd;
                padding: 8px;
                text-align: left;
            }}
            .info-table td:first-child {{
                background-color: #f0f0f0;
                font-weight: bold;
                width: 30%;
            }}
        </style>
    </head>
    <body>
        <div class="report-header">
            <div class="report-title">{member_name} 清洁设备工作分析报告</div>
            <div class="report-subtitle">{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}</div>
        </div>
        
        <div class="section">
            {report_tables.get('basic_info', '')}
        </div>
        
        <div class="section">
            {report_tables.get('attendance_analysis', '')}
        </div>
        
        <div class="section">
            {report_tables.get('region_breakdown', '')}
        </div>
        
        <div class="section">
            {report_tables.get('top_devices', '')}
        </div>
        
        <div class="section">
            {report_tables.get('bottom_devices', '')}
        </div>
        
        <div class="section">
            {report_tables.get('anomaly_detection', '')}
        </div>
        
        <div class="section">
            {report_tables.get('efficiency_distribution', '')}
        </div>
        
        <div class="section">
            {report_tables.get('summary_stats', '')}
        </div>
        
        <div class="ai-analysis">
            <h3>🤖 专业分析</h3>
            {''.join([f'<div class="ai-content"><h4>{title}</h4><div>{content}</div></div>' for title, content in ai_sections.items()])}
        </div>
    </body>
    </html>
    """
    
    return html_content


def render_health_final_report(complete_stats, report_tables, ai_content, member_name, start_time, end_time):
    """
    渲染最终健康报告HTML（专用于健康报告）
    
    Args:
        complete_stats: 完整健康统计数据
        report_tables: HTML表格
        ai_content: AI生成的分析内容
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: 最终的HTML健康报告
    """
    # 解析AI内容为段落（健康报告专用版）
    ai_sections = {}
    current_section = None
    current_content = []
    
    print(f"🔍 开始解析健康AI内容，总长度: {len(ai_content)} 字符")
    
    lines = ai_content.split('\n')
    for i, line in enumerate(lines):
        line = line.strip()
        
        # 检测多种标题格式（健康报告专用）
        is_title = False
        title_text = None
        
        # 格式1：**标题**
        if line.startswith('**') and line.endswith('**') and len(line) > 4:
            is_title = True
            title_text = line.strip('*').strip()
        # 格式2：第一部分 - 标题
        elif line.startswith('第') and ('部分' in line or '部分 -' in line):
            is_title = True
            title_text = line
        # 格式3：## 标题
        elif line.startswith('##') and len(line) > 3:
            is_title = True
            title_text = line.strip('#').strip()
        # 格式4：健康相关标题识别
        elif (line and not line.startswith('**') and 
              ('健康' in line or '状况' in line or '风险' in line or '建议' in line or '工作' in line or '发现' in line or '表现' in line) and
              len(line) < 50):
            # 检查是否像标题（短，包含健康关键词）
            if i > 0 and i < len(lines) - 1:
                prev_line = lines[i-1].strip()
                next_line = lines[i+1].strip()
                if not prev_line and next_line:  # 前面是空行，后面有内容
                    is_title = True
                    title_text = line
        
        if is_title:
            # 保存前一节内容
            if current_section and current_content:
                content_text = '<br><br>'.join(current_content)
                ai_sections[current_section] = content_text
                print(f"✅ 保存健康章节: {current_section} ({len(content_text)} 字符)")
            
            # 开始新节
            current_section = title_text
            current_content = []
            print(f"🆕 开始新健康章节: {current_section}")
        elif line and current_section:
            current_content.append(line)
        elif line and not current_section:
            # 如果还没有章节标题，但有内容，创建一个默认章节
            if not current_section:
                current_section = "健康状况分析"
                current_content = []
                print(f"🆕 创建默认健康章节: {current_section}")
            current_content.append(line)
    
    # 保存最后一节
    if current_section and current_content:
        content_text = '<br><br>'.join(current_content)
        ai_sections[current_section] = content_text
        print(f"✅ 保存最后健康章节: {current_section} ({len(content_text)} 字符)")
    
    # 如果完全没有解析出内容，创建一个兜底章节
    if not ai_sections and ai_content.strip():
        ai_sections["健康分析报告"] = ai_content.replace('\n', '<br>')
        print(f"🛡️ 创建兜底健康章节，原始内容长度: {len(ai_content)}")
    
    print(f"📊 健康AI内容解析完成，共{len(ai_sections)}个章节: {list(ai_sections.keys())}")
    
    # 获取健康评分和状态，用于标题样式
    health_score = complete_stats.get('health_assessment', {}).get('overall_health_score', 0)
    health_status = complete_stats.get('health_assessment', {}).get('health_status', '未知')
    exception_rate = complete_stats.get('basic_info', {}).get('exception_rate', 0)
    
    # 根据健康状况选择标题颜色
    if health_score >= 90:
        title_color = "#2E7D32"  # 深绿色 - 优秀
    elif health_score >= 80:
        title_color = "#388E3C"  # 绿色 - 良好  
    elif health_score >= 70:
        title_color = "#F57C00"  # 橙色 - 一般
    else:
        title_color = "#D32F2F"  # 红色 - 需要关注
    
    # 构建最终HTML（健康报告专用样式）
    html_content = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>{member_name} 员工健康异常分析报告</title>
        <style>
            body {{
                font-family: "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
                line-height: 1.6;
                margin: 40px;
                color: #333;
                background-color: #fff;
            }}
            .report-header {{
                text-align: center;
                margin-bottom: 40px;
                border-bottom: 2px solid #1f4e79;
                padding-bottom: 20px;
            }}
            .report-title {{
                font-size: 28px;
                color: #1f4e79;
                font-weight: bold;
                margin-bottom: 10px;
            }}
            .report-subtitle {{
                font-size: 18px;
                color: #666;
                margin-bottom: 20px;
            }}
            .health-indicator {{
                text-align: center;
                margin: 20px 0;
                padding: 15px;
                background: #f8f9fa;
                border: 1px solid #ddd;
            }}
            .health-score {{
                font-size: 20px;
                font-weight: bold;
                color: #1f4e79;
                margin: 5px 0;
            }}
            .health-status {{
                font-size: 16px;
                color: #666;
            }}
            .data-table {{
                width: 100%;
                border-collapse: collapse;
                margin-bottom: 25px;
                font-size: 14px;
            }}
            .data-table th, .data-table td {{
                border: 1px solid #ddd;
                padding: 12px;
                text-align: center;
            }}
            .data-table th {{
                background-color: #1f4e79;
                color: white;
                font-weight: bold;
            }}
            .data-table tr:nth-child(even) {{
                background-color: #f9f9f9;
            }}
            .info-table {{
                width: 100%;
                border-collapse: collapse;
                margin-bottom: 25px;
                font-size: 14px;
            }}
            .info-table td {{
                border: 1px solid #ddd;
                padding: 12px;
            }}
            .info-table td:first-child {{
                background-color: #f0f0f0;
                font-weight: bold;
                text-align: right;
                width: 40%;
            }}
            .info-table td:last-child {{
                text-align: left;
            }}
            .highlight-good {{
                background-color: #d4edda;
                color: #155724;
                font-weight: bold;
            }}
            .highlight-warning {{
                background-color: #fff3cd;
                color: #856404;
                font-weight: bold;
            }}
            .highlight-bad {{
                background-color: #f8d7da;
                color: #721c24;
                font-weight: bold;
            }}
            .basic-info-section, .health-overview-section, .exception-level-section, 
            .datatype-stats-section, .high-risk-section, .project-comparison-section,
            .risk-distribution-section, .urgent-attention-section, .severity-summary-section {{
                margin-bottom: 30px;
            }}
            .basic-info-section h3, .health-overview-section h3, .exception-level-section h3,
            .datatype-stats-section h3, .high-risk-section h3, .project-comparison-section h3,
            .risk-distribution-section h3, .urgent-attention-section h3, .severity-summary-section h3 {{
                color: #1f4e79;
                font-size: 18px;
                margin-bottom: 15px;
                border-bottom: 2px solid #1f4e79;
                padding-bottom: 5px;
            }}
            .ai-analysis {{
                margin-top: 40px;
                padding: 20px;
                border: 1px solid #ddd;
                background-color: #f8f9fa;
            }}
            .ai-analysis h3 {{
                color: #1f4e79;
                font-size: 20px;
                margin-bottom: 20px;
                text-align: center;
                border-bottom: 2px solid #1f4e79;
                padding-bottom: 10px;
            }}
            .ai-content {{
                margin: 15px 0;
                padding: 15px;
                background: white;
                border: 1px solid #ddd;
            }}
            .ai-content h4 {{
                color: #1f4e79;
                font-size: 16px;
                margin: 0 0 10px 0;
                border-bottom: 1px solid #ddd;
                padding-bottom: 5px;
            }}
            .ai-content div {{
                color: #333;
                line-height: 1.6;
                font-size: 14px;
            }}
        </style>
    </head>
    <body>
            <!-- 报告标题 -->
            <div class="report-header">
                <h1 class="report-title">🩺 {member_name} 员工健康异常分析报告</h1>
                <p class="report-subtitle">
                    报告期间：{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}
                    &nbsp;&nbsp;|&nbsp;&nbsp;
                    生成时间：{datetime.now().strftime('%Y年%m月%d日 %H:%M')}
                </p>
                <div class="health-indicator">
                    <div class="health-score">健康评分：{health_score} 分</div>
                    <div class="health-status">健康状况：{health_status}</div>
                    <div class="health-status">异常率：{exception_rate:.1%}</div>
                </div>
            </div>
            
            <!-- 数据表格区域 -->
            {report_tables.get('basic_info', '')}
            {report_tables.get('health_overview', '')}
            {report_tables.get('exception_level_stats', '')}
            {report_tables.get('datatype_stats', '')}
            {report_tables.get('high_risk_employees', '')}
            {report_tables.get('project_comparison', '')}
            {report_tables.get('risk_distribution', '')}
            {report_tables.get('time_analysis', '')}
            {report_tables.get('urgent_attention', '')}
            {report_tables.get('severity_summary', '')}
            
            <!-- AI分析区域 -->
            <div class="ai-analysis">
                <h3>🤖 专业健康分析</h3>
                {''.join([f'<div class="ai-content"><h4>{title}</h4><div>{content}</div></div>' for title, content in ai_sections.items()])}
            </div>
            
            <!-- 页脚 -->
            <div class="footer">
                <p>本报告由智能健康监测系统自动生成 | 数据来源：员工健康监测设备</p>
                <p>如有疑问，请联系系统管理员 | 报告仅供参考，具体健康问题请咨询专业医生</p>
            </div>
        </div>
    </body>
    </html>
    """
    
    return html_content


def df_to_csv_str(df: pd.DataFrame, **kwargs) -> str:
    """将DataFrame转换为CSV格式字符串"""
    return df.to_csv(index=False, encoding="utf-8", **kwargs)


class Report:
    def __init__(self, data):
        self.data = data
        self.start_time, self.end_time, self.total_days = get_data_range_from_utc_date_str(data)
        self.df_base = pd.read_excel(data['baseFile'])
        self.df_work = pd.read_excel(data['workFile'])
        self.df_clock_in = get_attendance_rate(self.df_base, self.df_work, self.total_days)
        self.df_clock_in["出勤率"] = self.df_clock_in["出勤率"].apply(lambda x: f"{x:.2f}%")
        self.df_clock_in["达标率"] = self.df_clock_in["达标天数"] / self.df_clock_in["工作天数"] * 100
